This page lists ready to run shogun examples for the C++ libshogun interface.
To run the examples you will need to manually compile them via
g++ name_of_example.cpp -lshogun
in case you installed libshogun to a nonstandard directory you will need to specify the appropriate library and include paths, e.g.
g++ -I/path/to/libshogun/includes name_of_example.cpp -L/path/to/libshogun/sofile -lshogun
Then the examples are standard binary executables and can be started via
./name_of_example
respectively if the libraries are in nonstandard locations (such that they cannot be found by the dynamic linker)
LD_LIBRARY_PATH=path/to/libshogun ./name_of_example
#include <shogun/base/init.h> using namespace shogun; int main(int argc, char** argv) { init_shogun(); exit_shogun(); return 0; }
/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Written (W) 2008-2009 Soeren Sonnenburg * Copyright (C) 2008-2009 Fraunhofer Institute FIRST and Max Planck Society */ #include <shogun/kernel/GaussianKernel.h> #include <shogun/features/SimpleFeatures.h> #include <shogun/classifier/svm/LibSVM.h> #include <shogun/lib/Mathematics.h> #include <shogun/lib/common.h> #include <shogun/base/init.h> #include <stdlib.h> #include <stdio.h> using namespace shogun; #define NUM 100 #define DIMS 2 #define DIST 0.5 float64_t* lab; float64_t* feat; void gen_rand_data() { lab=new float64_t[NUM]; feat=new float64_t[NUM*DIMS]; for (int32_t i=0; i<NUM; i++) { if (i<NUM/2) { lab[i]=-1.0; for (int32_t j=0; j<DIMS; j++) feat[i*DIMS+j]=CMath::random(0.0,1.0)+DIST; } else { lab[i]=1.0; for (int32_t j=0; j<DIMS; j++) feat[i*DIMS+j]=CMath::random(0.0,1.0)-DIST; } } CMath::display_vector(lab,NUM); CMath::display_matrix(feat,DIMS, NUM); } int main() { const int32_t feature_cache=0; const int32_t kernel_cache=0; const float64_t rbf_width=10; const float64_t svm_C=10; const float64_t svm_eps=0.001; init_shogun(); gen_rand_data(); // create train labels CLabels* labels=new CLabels(); labels->set_labels(lab, NUM); SG_REF(labels); // create train features CSimpleFeatures<float64_t>* features = new CSimpleFeatures<float64_t>(feature_cache); SG_REF(features); features->set_feature_matrix(feat, DIMS, NUM); // create gaussian kernel CGaussianKernel* kernel = new CGaussianKernel(kernel_cache, rbf_width); SG_REF(kernel); kernel->init(features, features); // create svm via libsvm and train CLibSVM* svm = new CLibSVM(svm_C, kernel, labels); SG_REF(svm); svm->set_epsilon(svm_eps); svm->train(); printf("num_sv:%d b:%f\n", svm->get_num_support_vectors(), svm->get_bias()); // classify + display output CLabels* out_labels=svm->classify(); for (int32_t i=0; i<NUM; i++) printf("out[%d]=%f\n", i, out_labels->get_label(i)); SG_UNREF(labels); SG_UNREF(out_labels); SG_UNREF(kernel); SG_UNREF(features); SG_UNREF(svm); exit_shogun(); return 0; }
#include <shogun/features/Labels.h> #include <shogun/features/SimpleFeatures.h> #include <shogun/kernel/GaussianKernel.h> #include <shogun/classifier/svm/LibSVM.h> #include <shogun/base/init.h> #include <shogun/lib/common.h> #include <shogun/lib/io.h> #include <stdio.h> using namespace shogun; void print_message(FILE* target, const char* str) { fprintf(target, "%s", str); } int main(int argc, char** argv) { init_shogun(&print_message); // create some data float64_t* matrix = new float64_t[6]; for (int32_t i=0; i<6; i++) matrix[i]=i; // create three 2-dimensional vectors // shogun will now own the matrix created CSimpleFeatures<float64_t>* features= new CSimpleFeatures<float64_t>(); features->set_feature_matrix(matrix, 2, 3); // create three labels CLabels* labels=new CLabels(3); labels->set_label(0, -1); labels->set_label(1, +1); labels->set_label(2, -1); // create gaussian kernel with cache 10MB, width 0.5 CGaussianKernel* kernel = new CGaussianKernel(10, 0.5); kernel->init(features, features); // create libsvm with C=10 and train CLibSVM* svm = new CLibSVM(10, kernel, labels); svm->train(); // classify on training examples for (int32_t i=0; i<3; i++) SG_SPRINT("output[%d]=%f\n", i, svm->classify_example(i)); // free up memory SG_UNREF(svm); exit_shogun(); return 0; }
/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Written (W) 2009 Alexander Binder * Copyright (C) 2009 Fraunhofer Institute FIRST and Max-Planck-Society */ #include <iostream> #include <shogun/lib/io.h> #include <shogun/lib/ShogunException.h> #include <shogun/kernel/CustomKernel.h> #include <shogun/kernel/CombinedKernel.h> #include <shogun/classifier/mkl/MKLMultiClass.h> // g++ -Wall -O3 classifier_mklmulticlass.cpp -I /home/theseus/private/alx/shoguntrunk/compiledtmp/include -L/home/theseus/private/alx/shoguntrunk/compiledtmp/lib -lshogun using namespace shogun; void print_message(FILE* target, const char* str) { fprintf(target, "%s", str); } void print_warning(FILE* target, const char* str) { fprintf(target, "%s", str); } void print_error(FILE* target, const char* str) { fprintf(target, "%s", str); } void getgauss(float64_t & y1, float64_t & y2) { float x1, x2, w; do { x1 = 2.0 * rand()/(float64_t)RAND_MAX - 1.0; x2 = 2.0 * rand()/(float64_t)RAND_MAX - 1.0; w = x1 * x1 + x2 * x2; } while ( (w >= 1.0)|| (w<1e-9) ); w = sqrt( (-2.0 * log( w ) ) / w ); y1 = x1 * w; y2 = x2 * w; } void gendata(std::vector<float64_t> & x,std::vector<float64_t> & y, CLabels*& lab) { int32_t totalsize=240; int32_t class1size=80; int32_t class2size=70; //generating three class data set x.resize(totalsize); y.resize(totalsize); for(size_t i=0; i< x.size();++i) getgauss(x[i], y[i]); for(size_t i=0; i< x.size();++i) { if((int32_t)i < class1size) { x[i]+=0; y[i]+=0; } else if( (int32_t)i< class1size+class2size) { x[i]+=+1; y[i]+=-1; } else { x[i]+=-1; y[i]+=+1; } } //set labels lab=new CLabels(x.size()); for(size_t i=0; i< x.size();++i) { if((int32_t)i < class1size) lab->set_int_label(i,0); else if( (int32_t)i< class1size+class2size) lab->set_int_label(i,1); else lab->set_int_label(i,2); } } void gentrainkernel(float64_t * & ker1 ,float64_t * & ker2, float64_t * & ker3 ,float64_t & autosigma,float64_t & n1,float64_t & n2, float64_t & n3, const std::vector<float64_t> & x, const std::vector<float64_t> & y) { autosigma=0; for(size_t l=0; l< x.size();++l) { for(size_t r=0; r<= l;++r) { float64_t dist=((x[l]-x[r])*(x[l]-x[r]) + (y[l]-y[r])*(y[l]-y[r])); autosigma+=dist*2.0/(float64_t)x.size()/((float64_t)x.size()+1); } } float64_t fm1=0, mean1=0,fm2=0, mean2=0,fm3=0, mean3=0; ker1=new float64_t[ x.size()*x.size()]; ker2=new float64_t[ x.size()*x.size()]; ker3=new float64_t[ x.size()*x.size()]; for(size_t l=0; l< x.size();++l) { for(size_t r=0; r< x.size();++r) { float64_t dist=((x[l]-x[r])*(x[l]-x[r]) + (y[l]-y[r])*(y[l]-y[r])); ker1[l +r*x.size()]= exp( -dist/autosigma/autosigma) ; //ker2[l +r*x.size()]= exp( -dist/sigma2/sigma2) ; ker2[l +r*x.size()]= x[l]*x[r] + y[l]*y[r]; ker3[l +r*x.size()]= (x[l]*x[r] + y[l]*y[r]+1)*(x[l]*x[r] + y[l]*y[r]+1); fm1+=ker1[l +r*x.size()]/(float64_t)x.size()/((float64_t)x.size()); fm2+=ker2[l +r*x.size()]/(float64_t)x.size()/((float64_t)x.size()); fm3+=ker3[l +r*x.size()]/(float64_t)x.size()/((float64_t)x.size()); if(l==r) { mean1+=ker1[l +r*x.size()]/(float64_t)x.size(); mean2+=ker2[l +r*x.size()]/(float64_t)x.size(); mean3+=ker3[l +r*x.size()]/(float64_t)x.size(); } } } n1=(mean1-fm1); n2=(mean2-fm2); n3=(mean3-fm3); for(size_t l=0; l< x.size();++l) { for(size_t r=0; r< x.size();++r) { ker1[l +r*x.size()]=ker1[l +r*x.size()]/n1; ker2[l +r*x.size()]=ker2[l +r*x.size()]/n2; ker3[l +r*x.size()]=ker3[l +r*x.size()]/n3; } } } void gentestkernel(float64_t * & ker1 ,float64_t * & ker2,float64_t * & ker3, const float64_t autosigma,const float64_t n1,const float64_t n2, const float64_t n3, const std::vector<float64_t> & x,const std::vector<float64_t> & y, const std::vector<float64_t> & tx,const std::vector<float64_t> & ty) { ker1=new float64_t[ x.size()*tx.size()]; ker2=new float64_t[ x.size()*tx.size()]; ker3=new float64_t[ x.size()*tx.size()]; for(size_t l=0; l< x.size();++l) { for(size_t r=0; r< tx.size();++r) { float64_t dist=((x[l]-tx[r])*(x[l]-tx[r]) + (y[l]-ty[r])*(y[l]-ty[r])); ker1[l +r*x.size()]= exp( -dist/autosigma/autosigma) ; ker2[l +r*x.size()]= x[l]*tx[r] + y[l]*ty[r]; ker3[l +r*x.size()]= (x[l]*tx[r] + y[l]*ty[r]+1)*(x[l]*tx[r] + y[l]*ty[r]+1); } } for(size_t l=0; l< x.size();++l) { for(size_t r=0; r< tx.size();++r) { ker1[l +r*x.size()]=ker1[l +r*x.size()]/n1; ker2[l +r*x.size()]=ker2[l +r*x.size()]/n2; ker3[l +r*x.size()]=ker3[l +r*x.size()]/n2; } } } void tester() { CLabels* lab=NULL; std::vector<float64_t> x,y; gendata(x,y, lab); SG_REF(lab); float64_t* ker1=NULL; float64_t* ker2=NULL; float64_t* ker3=NULL; float64_t autosigma=1; float64_t n1=0; float64_t n2=0; float64_t n3=0; int32_t numdata=0; gentrainkernel( ker1 , ker2, ker3 , autosigma, n1, n2, n3,x,y); numdata=x.size(); CCombinedKernel* ker=new CCombinedKernel(); CCustomKernel* kernel1=new CCustomKernel(); CCustomKernel* kernel2=new CCustomKernel(); CCustomKernel* kernel3=new CCustomKernel(); kernel1->set_full_kernel_matrix_from_full(ker1, numdata,numdata); kernel2->set_full_kernel_matrix_from_full(ker2, numdata,numdata); kernel3->set_full_kernel_matrix_from_full(ker3, numdata,numdata); ker->append_kernel(kernel1); ker->append_kernel(kernel2); ker->append_kernel(kernel3); //here comes the core stuff float64_t regconst=1.0; CMKLMultiClass* tsvm =new CMKLMultiClass(regconst, ker, lab); tsvm->set_epsilon(0.0001); // SVM epsilon // MKL parameters tsvm->set_mkl_epsilon(0.01); // subkernel weight L2 norm termination criterion tsvm->set_max_num_mkliters(120); // well it will be just three iterations tsvm->set_mkl_norm(1.5); // mkl norm //starting svm training tsvm->train(); SG_SPRINT("finished svm training\n"); //starting svm testing on training data CLabels* res=tsvm->classify(); ASSERT(res); float64_t err=0; for(int32_t i=0; i<numdata;++i) { ASSERT(i< res->get_num_labels()); if (lab->get_int_label(i)!=res->get_int_label(i)) err+=1; } err/=(float64_t)res->get_num_labels(); SG_SPRINT("prediction error on training data (3 classes): %f ",err); SG_SPRINT("random guess error would be: %f \n",2/3.0); delete[] ker1; delete[] ker2; delete[] ker3; //generate test data CLabels* tlab=NULL; std::vector<float64_t> tx,ty; gendata( tx,ty,tlab); SG_REF(tlab); float64_t* tker1=NULL; float64_t* tker2=NULL; float64_t* tker3=NULL; gentestkernel(tker1,tker2,tker3, autosigma, n1,n2,n3, x,y, tx,ty); int32_t numdatatest=tx.size(); CCombinedKernel* tker=new CCombinedKernel(); SG_REF(tker); CCustomKernel* tkernel1=new CCustomKernel(); CCustomKernel* tkernel2=new CCustomKernel(); CCustomKernel* tkernel3=new CCustomKernel(); tkernel1->set_full_kernel_matrix_from_full(tker1,numdata, numdatatest); tkernel2->set_full_kernel_matrix_from_full(tker2,numdata, numdatatest); tkernel3->set_full_kernel_matrix_from_full(tker2,numdata, numdatatest); tker->append_kernel(tkernel1); tker->append_kernel(tkernel2); tker->append_kernel(tkernel3); int32_t numweights; float64_t* weights=tsvm->getsubkernelweights(numweights); SG_SPRINT("test kernel weights\n"); for(int32_t i=0; i< numweights;++i) SG_SPRINT("%f ", weights[i]); SG_SPRINT("\n"); //set kernel tker->set_subkernel_weights(weights, numweights); tsvm->set_kernel(tker); //compute classif error, check mem CLabels* tres=tsvm->classify(); float64_t terr=0; for(int32_t i=0; i<numdatatest;++i) { ASSERT(i< tres->get_num_labels()); if(tlab->get_int_label(i)!=tres->get_int_label(i)) terr+=1; } terr/=(float64_t) tres->get_num_labels(); SG_SPRINT("prediction error on test data (3 classes): %f ",terr); SG_SPRINT("random guess error would be: %f \n",2/3.0); delete[] tker1; delete[] tker2; delete[] tker3; SG_UNREF(tsvm); SG_UNREF(res); SG_UNREF(tres); SG_UNREF(lab); SG_UNREF(tlab); SG_UNREF(tker); delete[] weights; weights=NULL; SG_SPRINT( "finished \n"); } namespace shogun { extern Version* sg_version; extern IO* sg_io; } int main() { init_shogun(&print_message, &print_warning, &print_error); try { sg_version->print_version(); sg_io->set_loglevel(MSG_INFO); tester(); } catch(ShogunException & sh) { printf("%s",sh.get_exception_string()); } exit_shogun(); }
#include <shogun/features/SimpleFeatures.h> #include <shogun/kernel/GaussianKernel.h> #include <shogun/base/init.h> #include <shogun/lib/common.h> #include <shogun/lib/io.h> #include <stdio.h> using namespace shogun; void print_message(FILE* target, const char* str) { fprintf(target, "%s", str); } int main(int argc, char** argv) { init_shogun(&print_message); // create some data float64_t* matrix = new float64_t[6]; for (int32_t i=0; i<6; i++) matrix[i]=i; // create three 2-dimensional vectors // shogun will now own the matrix created CSimpleFeatures<float64_t>* features= new CSimpleFeatures<float64_t>(); features->set_feature_matrix(matrix, 2, 3); // create gaussian kernel with cache 10MB, width 0.5 CGaussianKernel* kernel = new CGaussianKernel(features, features, 10, 0.5); // print kernel matrix for (int32_t i=0; i<3; i++) { for (int32_t j=0; j<3; j++) { SG_SPRINT("%f ", kernel->kernel(i,j)); } SG_SPRINT("\n"); } // free up memory SG_UNREF(kernel); exit_shogun(); return 0; }
#include <shogun/features/SimpleFeatures.h> #include <shogun/kernel/DotKernel.h> #include <shogun/base/init.h> #include <shogun/lib/common.h> #include <shogun/lib/io.h> #include <stdio.h> using namespace shogun; class CReverseLinearKernel : public CDotKernel { public: /** default constructor */ CReverseLinearKernel() : CDotKernel(0) { } /** destructor */ virtual ~CReverseLinearKernel() { } /** initialize kernel * * @param l features of left-hand side * @param r features of right-hand side * @return if initializing was successful */ virtual bool init(CFeatures* l, CFeatures* r) { CDotKernel::init(l, r); return init_normalizer(); } /** load kernel init_data * * @param src file to load from * @return if loading was successful */ virtual bool load_init(FILE* src) { return false; } /** save kernel init_data * * @param dest file to save to * @return if saving was successful */ virtual bool save_init(FILE* dest) { return false; } /** return what type of kernel we are * * @return kernel type UNKNOWN (as it is not part * officially part of shogun) */ virtual EKernelType get_kernel_type() { return K_UNKNOWN; } /** return the kernel's name * * @return name "Reverse Linear" */ inline virtual const char* get_name() const { return "ReverseLinear"; } protected: /** compute kernel function for features a and b * idx_{a,b} denote the index of the feature vectors * in the corresponding feature object * * @param idx_a index a * @param idx_b index b * @return computed kernel function at indices a,b */ virtual float64_t compute(int32_t idx_a, int32_t idx_b) { int32_t alen, blen; bool afree, bfree; float64_t* avec= ((CSimpleFeatures<float64_t>*) lhs)->get_feature_vector(idx_a, alen, afree); float64_t* bvec= ((CSimpleFeatures<float64_t>*) rhs)->get_feature_vector(idx_b, blen, bfree); ASSERT(alen==blen); float64_t result=0; for (int32_t i=0; i<alen; i++) result+=avec[i]*bvec[alen-i-1]; ((CSimpleFeatures<float64_t>*) lhs)->free_feature_vector(avec, idx_a, afree); ((CSimpleFeatures<float64_t>*) rhs)->free_feature_vector(bvec, idx_b, bfree); return result; } }; void print_message(FILE* target, const char* str) { fprintf(target, "%s", str); } int main(int argc, char** argv) { init_shogun(&print_message); // create some data float64_t* matrix = new float64_t[6]; for (int32_t i=0; i<6; i++) matrix[i]=i; // create three 2-dimensional vectors // shogun will now own the matrix created CSimpleFeatures<float64_t>* features= new CSimpleFeatures<float64_t>(); features->set_feature_matrix(matrix, 2, 3); // create gaussian kernel with cache 10MB, width 0.5 CReverseLinearKernel* kernel = new CReverseLinearKernel(); kernel->init(features,features); // print kernel matrix for (int32_t i=0; i<3; i++) { for (int32_t j=0; j<3; j++) SG_SPRINT("%f ", kernel->kernel(i,j)); SG_SPRINT("\n"); } // free up memory SG_UNREF(kernel); exit_shogun(); return 0; }
/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Written (W) 2009 Soeren Sonnenburg * Copyright (C) 2009 Fraunhofer Institute FIRST and Max-Planck-Society */ #include <shogun/lib/io.h> #include <shogun/lib/Time.h> #include <shogun/lib/ShogunException.h> #include <shogun/lib/Mathematics.h> #include <shogun/lib/DynInt.h> using namespace shogun; void print_message(FILE* target, const char* str) { fprintf(target, "%s", str); } void print_warning(FILE* target, const char* str) { fprintf(target, "%s", str); } void print_error(FILE* target, const char* str) { fprintf(target, "%s", str); } void gen_ints(uint256_t* &a, uint32_t* &b, uint32_t len) { a=new uint256_t[len]; b=new uint32_t[len]; CMath::init_random(17); for (uint32_t i=0; i<len; i++) { uint64_t r[4]={(uint64_t) CMath::random() << 32 | CMath::random(), (uint64_t) CMath::random() << 32 | CMath::random(), (uint64_t) CMath::random() << 32 | CMath::random(), (uint64_t) CMath::random() << 32 | CMath::random()}; a[len-i-1]=r; b[len-i-1]=i; } } const int LEN = 5*1024*1024; int main() { init_shogun(&print_message, &print_warning, &print_error); try { uint256_t* a; uint32_t* b; CTime t; t.io->set_loglevel(MSG_DEBUG); SG_SPRINT("gen data.."); t.start(); gen_ints(a,b, LEN); t.cur_time_diff(true); SG_SPRINT("qsort.."); t.start(); CMath::qsort_index(a, b, LEN); t.cur_time_diff(true); SG_SPRINT("\n\n"); for (uint32_t i=0; i<10; i++) { SG_SPRINT("a[%d]=", i); a[i].print_hex(); SG_SPRINT("\n"); } SG_SPRINT("\n\n"); a[0]=(uint64_t[4]) {1,2,3,4}; uint64_t val[4]={5,6,7,8}; a[1]=val; a[2]=a[0]; CMath::swap(a[0],a[1]); printf("a[0]==a[1] %d\n", (int) (a[0] == a[1])); printf("a[0]<a[1] %d\n", (int) (a[0] < a[1])); printf("a[0]<=a[1] %d\n", (int) (a[0] <= a[1])); printf("a[0]>a[1] %d\n", (int) (a[0] > a[1])); printf("a[0]>=a[1] %d\n", (int) (a[0] >= a[1])); printf("a[0]==a[0] %d\n", (int) (a[0] == a[0])); printf("a[0]<a[0] %d\n", (int) (a[0] < a[0])); printf("a[0]<=a[0] %d\n", (int) (a[0] <= a[0])); printf("a[0]>a[0] %d\n", (int) (a[0] > a[0])); printf("a[0]>=a[0] %d\n", (int) (a[0] >= a[0])); SG_SPRINT("\n\n"); for (uint32_t i=0; i<10 ; i++) { SG_SPRINT("a[%d]=", i); a[i].print_hex(); printf("\n"); } delete[] a; delete[] b; } catch(ShogunException & sh) { SG_SPRINT("%s",sh.get_exception_string()); } exit_shogun(); }
#include <shogun/base/init.h> #include <shogun/lib/common.h> #include <shogun/lib/GCArray.h> #include <shogun/kernel/Kernel.h> #include <shogun/kernel/GaussianKernel.h> #include <stdio.h> using namespace shogun; const int l=10; int main(int argc, char** argv) { init_shogun(); // create array a CGCArray<CKernel*> kernels(l); for (int i=0; i<l; i++) kernels.set(new CGaussianKernel(10, 1.0), i); for (int i=0; i<l; i++) printf("kernels[%d]=%p\n", i, kernels.get(i)); exit_shogun(); return 0; }
#include <shogun/lib/Hash.h> #include <stdio.h> using namespace shogun; int main(int argc, char** argv) { init_shogun(); uint8_t array[4]={0,1,2,3}; printf("hash(0)=%0x\n", CHash::MurmurHash2(&array[0], 1, 0xDEADBEAF)); printf("hash(1)=%0x\n", CHash::MurmurHash2(&array[1], 1, 0xDEADBEAF)); printf("hash(2)=%0x\n", CHash::MurmurHash2(&array[0], 2, 0xDEADBEAF)); printf("hash(3)=%0x\n", CHash::MurmurHash2(&array[0], 4, 0xDEADBEAF)); uint32_t h=CHash::IncrementalMurmurHash2(array[0], 0xDEADBEAF); printf("inc_hash(0)=%0x\n", h); h=CHash::IncrementalMurmurHash2(array[1], h); printf("inc_hash(1)=%0x\n", h); h=CHash::IncrementalMurmurHash2(array[2], h); printf("inc_hash(2)=%0x\n", h); h=CHash::IncrementalMurmurHash2(array[3], h); printf("inc_hash(3)=%0x\n", h); exit_shogun(); return 0; }
#include <shogun/base/init.h> #include <shogun/lib/common.h> #include <shogun/lib/IndirectObject.h> #include <shogun/lib/Mathematics.h> #include <shogun/base/SGObject.h> #include <stdio.h> using namespace shogun; const int l=10; int main(int argc, char** argv) { init_shogun(); // create array a int32_t* a=new int32_t[l]; for (int i=0; i<l; i++) a[i]=l-i; // create array of indirect objects pointing to array a CIndirectObject<int32_t, int32_t**>::set_array(&a); CIndirectObject<int32_t, int32_t**>* x = new CIndirectObject<int32_t, int32_t**>[l]; CIndirectObject<int32_t, int32_t**>::init_slice(x, l); printf("created array a and indirect object array x pointing to a.\n\n"); for (int i=0; i<l; i++) printf("a[%d]=%d x[%d]=%d\n", i, a[i], i, int32_t(x[i])); //sort the array CMath::qsort(x, l); printf("\n\nvoila! sorted indirect object array x, keeping a const.\n\n"); for (int i=0; i<l; i++) printf("a[%d]=%d x[%d]=%d\n", i, a[i], i, int32_t(x[i])); exit_shogun(); return 0; }