SHARE
TWEET

Untitled

a guest Aug 10th, 2014 254 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include "EXTERN.h"
  2. #include "perl.h"
  3. #include "XSUB.h"
  4.  
  5. #include <math.h>
  6. #include "FastSOM.h"
  7. #include "proto.h"
  8. #include "omp.h"
  9. #include <stdio.h>
  10.  
  11. /*
  12.  * generic funtions
  13.  *
  14.  * NOT superclass functions, but usable by all
  15.  */
  16.  
  17. NV _vector_distance(AV* V1, AV* V2) {
  18.         NV      diff,sum;
  19.         I32     w_ptr;
  20.  
  21.         sum = 0;
  22.         for ( w_ptr=av_len(V2) ; w_ptr>=0 ; w_ptr-- ) {
  23.                 diff = SvNV(*av_fetch(V1, w_ptr, FALSE))
  24.                         - SvNV(*av_fetch(V2, w_ptr, FALSE));
  25.                 sum += diff * diff;
  26.         }
  27.         return sqrt(sum);
  28. }
  29.  
  30. void _bmuguts(SOM_GENERIC *som,AV *sample,IV *bx,IV *by,NV *bd) {
  31.         IV              x,y,z,X,Y,Z;
  32.         NV              sum,diff,distance;
  33.         SOM_Map         *map;
  34.         SOM_Array       *array;
  35.         SOM_Vector      *vector;
  36.  
  37.         map = som->map;
  38.         X = som->X;
  39.         Y = som->Y;
  40.         Z = som->Z;
  41.  
  42.         *bx = -1;
  43.         *by = 0;
  44.         *bd = 0.0;
  45.         for ( x=0 ; x<X ; x++ ) {
  46.                 array = (&map->array)[x];
  47.                 for ( y=0 ; y<Y ; y++ ) {
  48.                         vector = (&array->vector)[y];
  49.  
  50.                         sum = 0;
  51.                         for ( z=0 ; z<Z ; z++ ) {
  52.                                 diff = SvNV(*av_fetch(sample,z,0))
  53.                                         - (&vector->element)[z];
  54.                                 sum += diff * diff;
  55.                         }
  56.                         distance = sqrt(sum);
  57.  
  58.                         if ( *bx < 0 )
  59.                                 { *bx = 0; *by = 0; *bd = distance; }
  60.                         if ( distance < *bd )
  61.                                 { *bx = x; *by = y; *bd = distance; }
  62.                 }
  63.         }
  64. }
  65.  
  66.  
  67. /* http://www.ai-junkie.com/ann/som/som4.html */
  68. void _adjust(SV* self,NV l,NV sigma,AV* unit,AV* v) {
  69.         IV              x,y;
  70.         I32             z,Z;
  71.         NV              d,theta,vold,wold;
  72.         MAGIC           *mg;
  73.         SOM_Map         *map;
  74.         SOM_Array       *array;
  75.         SOM_Vector      *vector;
  76.         SOM_GENERIC     *som;
  77.  
  78.         x = SvIV(*av_fetch(unit, 0, FALSE));
  79.         y = SvIV(*av_fetch(unit, 1, FALSE));
  80.         d = SvNV(*av_fetch(unit, 2, FALSE));
  81.         theta = exp( -d*d/2/sigma/sigma );
  82.  
  83.         if ( !(mg = selfmagic(self)) )
  84.                 croak("self has no magic!\n");
  85.         som = self2somptr(self,mg);
  86.  
  87.         map = som->map;
  88.         array = (&map->array)[x];
  89.         vector = (&array->vector)[y];
  90.  
  91.         /* hmm.. casting IV to I32.. is that sane? */
  92.         Z = (I32)som->Z;
  93.  
  94.         for ( z=0 ; z<Z ; z++ ) {
  95.                 wold = (&vector->element)[z];
  96.                 vold = SvNV(*av_fetch(v,z,FALSE));
  97.                 (&vector->element)[z] = (vold - wold) * l * theta + wold;
  98.         }
  99. }
  100.  
  101. void _adjustn(SOM_GENERIC* som,NV l,NV sigma,NV* n,AV* v) {
  102.         IV              x,y,X,Y;
  103.         I32             z,Z;
  104.         NV              d,theta,vold,wold;
  105.         SOM_Map         *map;
  106.         SOM_Array       *array;
  107.         SOM_Vector      *vector;
  108.  
  109.         map = som->map;
  110.         X = som->X;
  111.         Y = som->Y;
  112.  
  113.         for ( x=0 ; x<X ; x++ ) {
  114.                 array = (&map->array)[x];
  115.                 for ( y=0 ; y<Y ; y++ ) {
  116.                         d = n[x*Y+y];
  117.                         if (d < 0) continue;
  118.                         theta = exp( -d*d/2/sigma/sigma );
  119.                         vector = (&array->vector)[y];
  120.  
  121.                         /* hmm.. casting IV to I32.. is that sane? */
  122.                         Z = (I32)som->Z;
  123.  
  124.  
  125.                         for ( z=0 ; z<Z ; z++ ) {
  126.                                 wold = (&vector->element)[z];
  127.                                 vold = SvNV(*av_fetch(v,z,FALSE));
  128.                                 (&vector->element)[z] =
  129.                                         (vold - wold) * l * theta + wold;
  130.                         }
  131.                 }
  132.         }
  133.  
  134.  
  135. }
  136.  
  137. AV* _neighbors(SV* self,NV sigma,IV X0,IV Y0,...) {
  138.         IV              i,x,y,X,Y;
  139.         NV              distance,*n;
  140.         AV              *tmp,*neighbors;
  141.         MAGIC           *mg;
  142.         SOM_GENERIC     *som;
  143.         void            (*neiguts)(SOM_GENERIC* som,NV sigma,IV X0,IV Y0,NV *n);
  144.  
  145.         if ( !(mg = selfmagic(self)) )
  146.                 croak("self has no magic!\n");
  147.         som = self2somptr(self,mg);
  148.  
  149.         X = som->X;
  150.         Y = som->Y;
  151.  
  152.         i = X*Y;
  153.         Newx(n,i,NV);
  154.         for ( i-=1 ; i>=0 ; i-- )
  155.                 n[i] = -1;
  156.  
  157.         if ( som->type == SOMType_Torus )
  158.                 neiguts = _torus_neiguts;
  159.         else if ( som->type == SOMType_Hexa )
  160.                 neiguts = _hexa_neiguts;
  161.         else if ( som->type == SOMType_Rect )
  162.                 neiguts = _rect_neiguts;
  163.         else
  164.                 croak("unknown type");
  165.  
  166.         neiguts(som,sigma,X0,Y0,n);
  167.  
  168.         neighbors = newAV();
  169.  
  170.         for ( x=0 ; x<X ; x++ ) {
  171.                 for ( y=0 ; y<Y ; y++ ) {
  172.                         distance = n[x*Y+y];
  173.                         if ( distance >= 0 ) {
  174.                                 tmp = newAV();
  175.                                 av_push(tmp,newSViv(x));
  176.                                 av_push(tmp,newSViv(y));
  177.                                 av_push(tmp,newSVnv(distance));
  178.                                 av_push(neighbors,newRV_noinc((SV*)tmp));
  179.                         }
  180.                 }
  181.         }
  182.         Safefree(n);
  183.         return neighbors;
  184. }
  185.  
  186. SOM_Vector* _make_vector(SOM_Array* array) {
  187.         IV              z,len;
  188.         AV              *thingy;
  189.         SV              *tie;
  190.         HV              *stash;
  191.         SOM_Vector      *vector;
  192.  
  193.         z = array->Z;
  194.  
  195.         len = sizeof(SOM_Vector)+z*sizeof(NV);
  196.         Newxc(vector, len, char, SOM_Vector);
  197.         Zero(vector, len, char);
  198.  
  199.         vector->Z = z;
  200.  
  201.         thingy = newAV();
  202.         tie = newRV_noinc(newSViv(PTR2IV(vector)));
  203.         stash = gv_stashpv("AI::NeuralNet::FastSOM::VECTOR", GV_ADD);
  204.         sv_bless(tie, stash);
  205.         hv_magic((HV*)thingy, (GV*)tie, 'P');
  206.         vector->ref = newRV_noinc((SV*)thingy);
  207.  
  208.         (&vector->element)[z] = 0.0;
  209.         for ( z-=1 ; z>=0 ; z-- ) {
  210.                 (&vector->element)[z] = 0.0;
  211.         }
  212.  
  213.         return vector;
  214. }
  215.  
  216. SOM_Array* _make_array(SOM_Map* map) {
  217.         IV              y,len;
  218.         AV              *thingy;
  219.         SV              *tie;
  220.         HV              *stash;
  221.         SOM_Array       *array;
  222.  
  223.         y = map->Y;
  224.  
  225.         len = sizeof(SOM_Array)+y*sizeof(SOM_Vector*);
  226.         Newxc(array, len, char, SOM_Array);
  227.         Zero(array, len, char);
  228.  
  229.         array->Y = y;
  230.         array->Z = map->Z;
  231.  
  232.         thingy = newAV();
  233.         tie = newRV_noinc(newSViv(PTR2IV(array)));
  234.         stash = gv_stashpv("AI::NeuralNet::FastSOM::ARRAY", GV_ADD);
  235.         sv_bless(tie, stash);
  236.         hv_magic((HV*)thingy, (GV*)tie, PERL_MAGIC_tied);
  237.         array->ref = newRV_noinc((SV*)thingy);
  238.  
  239.         (&array->vector)[y] = NULL;
  240.         for ( y-=1 ; y>=0 ; y-- )
  241.                 (&array->vector)[y] = _make_vector( array );
  242.  
  243.         return array;
  244. }
  245.  
  246. SOM_Map* _make_map(SOM_GENERIC *som) {
  247.         IV      x,len;
  248.         AV      *thingy;
  249.         SV      *tie;
  250.         HV      *stash;
  251.         SOM_Map *map;
  252.  
  253.         x = som->X;
  254.  
  255.         len = sizeof(SOM_Map)+x*sizeof(SOM_Array*);
  256.         Newxc(map, len, char, SOM_Map);
  257.         Zero(map, len, char);
  258.  
  259.         map->X = x;
  260.         map->Y = som->Y;
  261.         map->Z = som->Z;
  262.  
  263.         thingy = newAV();
  264.         tie = newRV_noinc(newSViv(PTR2IV(map)));
  265.         stash = gv_stashpv("AI::NeuralNet::FastSOM::MAP", GV_ADD);
  266.         sv_bless(tie, stash);
  267.         hv_magic((HV*)thingy, (GV*)tie, PERL_MAGIC_tied);
  268.         map->ref = newRV_noinc((SV*)thingy);
  269.  
  270.         (&map->array)[x] = NULL;
  271.         for ( x-=1 ; x>=0 ; x-- )
  272.                 (&map->array)[x] = _make_array( map );
  273.  
  274.         return map;
  275. }
  276.  
  277.  
  278.  
  279. /*
  280.  * som functions
  281.  */
  282.  
  283. void _som_bmu(SV* self, AV* sample) {
  284.         IV              cx,cy;
  285.         NV              cd;
  286.         MAGIC           *mg;
  287.         SOM_GENERIC     *som;
  288.         dXSARGS;
  289.  
  290.         if ( !(mg = selfmagic(self)) )
  291.                 croak("self has no magic!\n");
  292.         som = self2somptr(self,mg);
  293.  
  294.         _bmuguts(som,sample,&cx,&cy,&cd);
  295.  
  296.         PERL_UNUSED_VAR(items); /* -W */
  297.         sp = mark;
  298.         XPUSHs(sv_2mortal(newSViv(cx)));
  299.         XPUSHs(sv_2mortal(newSViv(cy)));
  300.         XPUSHs(sv_2mortal(newSVnv(cd)));
  301.         PUTBACK;
  302. }
  303.  
  304. SV* _som_map(SV* self) {
  305.         MAGIC           *mg;
  306.         SOM_GENERIC     *som;
  307.  
  308.         if ( !(mg = selfmagic(self)) )
  309.                 croak("self has no magic!\n");
  310.         som = self2somptr(self,mg);
  311.  
  312.         SvREFCNT_inc(som->map->ref);
  313.         return som->map->ref;
  314. }
  315.  
  316. SV* _som_output_dim(SV* self) {
  317.         MAGIC           *mg;
  318.         SOM_GENERIC     *som;
  319.  
  320.         if ( !(mg = selfmagic(self)) )
  321.                 croak("self has no magic!\n");
  322.         som = self2somptr(self,mg);
  323.  
  324.         SvREFCNT_inc(som->output_dim);
  325.         return som->output_dim;
  326. }
  327.  
  328. void _som_train(SV* self,IV epochs) {
  329.         IV              i,X,Y,bx,by,epoch;
  330.         NV              bd,l,sigma,*n;
  331.         AV              **org,**veg,*sample;
  332.         I32             p,pick,nitems,oitems,vitems,drnd;
  333.         MAGIC           *mg;
  334.         SOM_GENERIC     *som;
  335.         bool            wantarray;
  336.         void            (*neiguts)(SOM_GENERIC* som,NV sigma,IV X0,IV Y0,NV* n);
  337.         dXSARGS;
  338.  
  339.  
  340.        
  341.         int R;
  342.         if ( !(mg = selfmagic(self)) )
  343.                 croak("self has no magic!");
  344.         som = self2somptr(self,mg);
  345.  
  346.         if ( epochs < 1 )
  347.                 epochs = 1;
  348.  
  349.         if ( items < 3 )
  350.                 croak("no data to learn");
  351.  
  352.         oitems = items - 2;
  353.         Newx(org,oitems,AV*);
  354.         Newx(veg,oitems,AV*);
  355.  
  356.         for ( i=2 ; i<items ; i++ )
  357.                 if ( SvTYPE(SvRV(ST(i))) != SVt_PVAV )
  358.                         croak("training item %i is not an array ref", (int)i);
  359.                 else
  360.                         org[i-2] = (AV*)SvRV(ST(i));
  361.  
  362.         som->LAMBDA = epochs / log( som->Sigma0 );
  363.  
  364.         X = som->X;
  365.         Y = som->Y;
  366.  
  367.         nitems = X*Y;
  368.         Newx(n,nitems,NV);
  369.  
  370.         if ( som->type == SOMType_Torus )
  371.                 neiguts = _torus_neiguts;
  372.         else if ( som->type == SOMType_Hexa )
  373.                 neiguts = _hexa_neiguts;
  374.         else if ( som->type == SOMType_Rect )
  375.                 neiguts = _rect_neiguts;
  376.         else
  377.                 croak("unknown type");
  378.  
  379.         wantarray = GIMME_V == G_ARRAY ? TRUE : FALSE;
  380.  
  381.         /* should this be moved somewhere more global? */
  382.         if ( !PL_srand_called ) {
  383.                 seedDrand01((Rand_seed_t)(time(NULL)+PerlProc_getpid()));
  384.                 PL_srand_called = TRUE;
  385.         }
  386.  
  387.         sp = mark;
  388.  
  389.         int dd=0;
  390. #pragma omp parallel default(shared)
  391. {
  392. #pragma omp for
  393.         for ( epoch=1 ; epoch<=epochs ; epoch++ ) {
  394.                
  395.                 dd++;
  396.                 printf("epoch: %d \n", dd);
  397.                 som->T = epoch;
  398.                 sigma = som->Sigma0 * exp(-epoch / som->LAMBDA);
  399.                 l = som->L0 * exp(-epoch / epochs);
  400.  
  401.                 Copy(org,veg,oitems,AV*);
  402.                 vitems = oitems;
  403.                
  404. /*
  405.                 while ( vitems > 0 ) {
  406. */
  407.  
  408.                 for(vitems=oitems; vitems>0; vitems--) {
  409.  
  410.                
  411. /*
  412.                         pick = (I32)(Drand01() * vitems);
  413. */
  414.  
  415.                         drnd = Drand01();
  416.                         pick = drnd * vitems;
  417.  
  418.                         sample = (AV*)veg[pick];
  419.  
  420.                         /* optimze me! */
  421.                         for ( p=pick+1 ; p<vitems ; p++ ){
  422.                                 R=p-1; 
  423.                                 veg[R] = veg[p];
  424.                         }
  425.  
  426.                         /*
  427.                         vitems--;
  428.                         */
  429.                         _bmuguts(som,sample,&bx,&by,&bd);
  430.  
  431.                         if ( wantarray ) XPUSHs(newSVnv(bd));
  432.                        
  433.                         for ( i=0 ; i<nitems ; i++ ) n[i] = -1;
  434.                         neiguts(som,sigma,bx,by,n);
  435.  
  436.                         _adjustn(som,l,sigma,n,sample);
  437.                 }
  438.  
  439.         }
  440. }
  441.        
  442.  
  443.         Safefree(n);
  444.         Safefree(org);
  445.         Safefree(veg);
  446.  
  447.         PUTBACK;
  448. }
  449.  
  450. void _som_FREEZE(SV* self,SV* cloning) {
  451.         IV              x,y,z;
  452.         MAGIC           *mg;
  453.         SOM_Map         *m;
  454.         SOM_Array       *a;
  455.         SOM_Vector      *v;
  456.         SOM_GENERIC     *som;
  457.         dXSARGS;
  458.  
  459.         PERL_UNUSED_VAR(items); /* -W */
  460.         sp = mark;
  461.  
  462.         if ( !SvTRUE(cloning) ) {
  463.  
  464.         if ( (mg = selfmagic(self)) != NULL) {
  465.  
  466.                 /*
  467.                  * we should get here on the first pass. this is where we
  468.                  * serialize the hash seen from perl.
  469.                  */
  470.  
  471.                 XPUSHs(INT2PTR(SV*,newSVpvn("i wanna be a cowboy",19)));
  472.  
  473.         }
  474.         else if ( SvTYPE(SvRV(self)) == SVt_PVMG ) {
  475.  
  476.                 /*
  477.                  * this should be the second pass. here we need to serialize
  478.                  * the tied part not seen from the perl side.
  479.                  */
  480.  
  481.                 som = INT2PTR(SOM_GENERIC*,self2iv(self));
  482.  
  483.                 XPUSHs( INT2PTR(SV*,newSVpvn(
  484.                                 "beat me whip me make me code badly",34)) );
  485.                 XPUSHs( newRV_noinc(newSViv(som->type)) );
  486.                 XPUSHs( newRV_noinc(newSViv(som->X)) );
  487.                 XPUSHs( newRV_noinc(newSViv(som->Y)) );
  488.                 XPUSHs( newRV_noinc(newSViv(som->Z)) );
  489.                 XPUSHs( newRV_noinc(newSVnv(som->R)) );
  490.                 XPUSHs( newRV_noinc(newSVnv(som->Sigma0)) );
  491.                 XPUSHs( newRV_noinc(newSVnv(som->L0)) );
  492.                 XPUSHs( newRV_noinc(newSVnv(som->LAMBDA)) );
  493.                 XPUSHs( newRV_noinc(newSVnv(som->T)) );
  494.                 XPUSHs( newRV_noinc(som->output_dim) );
  495.                 XPUSHs( newRV_noinc((SV*)som->labels) );
  496.  
  497.                 m = som->map;
  498.                 for ( x=som->X-1 ; x>=0 ; x-- ) {
  499.                         a = (&m->array)[x];
  500.                         for ( y=som->Y-1 ; y>=0 ; y-- ) {
  501.                                 v = (&a->vector)[y];
  502.                                 for ( z=som->Z-1 ; z>=0 ; z-- ) {
  503.                                         XPUSHs(newRV_noinc(newSVnv(
  504.                                         (&v->element)[z])));
  505.                                 }
  506.                         }
  507.                 }
  508.         }
  509.         else {
  510.                 croak("i wanna run with scissors!");
  511.         }
  512.         } /* cloning */
  513.         PUTBACK;
  514. }
  515.  
  516. void _som_THAW(SV* self,SV* cloning,SV* serialized) {
  517.         IV              x,y,z,i;
  518.         SV              *rrr;
  519.         HV              *stash;
  520.         SOM_Map         *m;
  521.         SOM_Array       *a;
  522.         SOM_Vector      *v;
  523.         SOM_GENERIC     *som;
  524.         dXSARGS;
  525.  
  526.         PERL_UNUSED_VAR(serialized); /* -W */
  527.  
  528.         if (!SvTRUE(cloning)) {
  529.  
  530.         if ( SvTYPE(SvRV(self)) == SVt_PVMG ) {
  531.                 Newxz(som,1,SOM_GENERIC);
  532.  
  533.                 som->type = SvIV(SvRV(ST(3)));
  534.                 som->X = SvIV(SvRV(ST(4)));
  535.                 som->Y = SvIV(SvRV(ST(5)));
  536.                 som->Z = SvIV(SvRV(ST(6)));
  537.                 som->R = SvNV(SvRV(ST(7)));
  538.                 som->Sigma0 = SvNV(SvRV(ST(8)));
  539.                 som->L0 = SvNV(SvRV(ST(9)));
  540.                 som->LAMBDA = SvNV(SvRV(ST(10)));
  541.                 som->T = SvNV(SvRV(ST(11)));
  542.                 som->output_dim = newSVsv(SvRV(ST(12)));
  543.                 som->labels = (AV*)SvRV(ST(13));
  544.  
  545.                 som->map = _make_map( som );
  546.  
  547.                 i = 14;
  548.                 m = som->map;
  549.                 for ( x=som->X-1 ; x>=0 ; x-- ) {
  550.                         a = (&m->array)[x];
  551.                         for ( y=som->Y-1 ; y>=0 ; y-- ) {
  552.                                 v = (&a->vector)[y];
  553.                                 for ( z=som->Z-1 ; z>=0 ; z-- ) {
  554.                                         /*
  555.                                         (&v->element)[z] =
  556.                                                 SvNV(SvRV(ST(i++)));
  557.                                         */
  558.                                         rrr = SvRV(ST(i++));
  559.                                         (&v->element)[z] = SvNV(rrr);
  560.                                 }
  561.                         }
  562.                 }
  563.  
  564.                 SvSetSV( SvRV(self), sv_2mortal(newSViv((IV)PTR2IV(som))) );
  565.  
  566.                 stash = SvSTASH(SvRV(self));
  567.                 som->ref = sv_bless(newRV_inc((SV*)self),stash);
  568.  
  569.         }
  570.  
  571.         else if ( SvTYPE(SvRV(self)) != SVt_PVHV )
  572.                 croak("you'll put an eye out!");
  573.  
  574.         } /* cloning */
  575.  
  576.         PERL_UNUSED_VAR(items); /* -W */
  577.         sp = mark;
  578.         PUTBACK;
  579. }
  580.  
  581. SV* _som_FETCH(SV* self,SV* key) {
  582.         if ( !sv_cmp( key, INT2PTR(SV*,newSVpvn("map",3) ) ) ) {
  583.                 SOM_GENERIC *som = INT2PTR(SOM_Rect*,self2iv(self));
  584.                 SvREFCNT_inc(som->map->ref);
  585.                 return som->map->ref;
  586.         }
  587.         if ( !sv_cmp( key, INT2PTR(SV*,newSVpvn("_X",2) ) ) )
  588.                 return newSViv(tied2ptr(self)->X);
  589.         if ( !sv_cmp( key, INT2PTR(SV*,newSVpvn("_Y",2) ) ) )
  590.                 return newSViv(tied2ptr(self)->Y);
  591.         if ( !sv_cmp( key, INT2PTR(SV*,newSVpvn("_Z",2) ) ) )
  592.                 return newSViv(tied2ptr(self)->Z);
  593.         if ( !sv_cmp( key, INT2PTR(SV*,newSVpvn("_R",2) ) ) )
  594.                 return newSVnv(tied2ptr(self)->R);
  595.         if ( !sv_cmp( key, INT2PTR(SV*,newSVpvn("_L0",3) ) ) )
  596.                 return newSVnv(tied2ptr(self)->L0);
  597.         if ( !sv_cmp( key, INT2PTR(SV*,newSVpvn("_Sigma0",7) ) ) )
  598.                 return newSVnv(tied2ptr(self)->Sigma0);
  599.         if ( !sv_cmp( key, INT2PTR(SV*,newSVpvn("output_dim",10) ) ) )
  600.                 return newSVsv(tied2ptr(self)->output_dim);
  601.         if ( !sv_cmp( key, INT2PTR(SV*,newSVpvn("LAMBDA",6) ) ) )
  602.                 return newSVnv(tied2ptr(self)->LAMBDA);
  603.         if ( !sv_cmp( key, INT2PTR(SV*,newSVpvn("T",1) ) ) )
  604.                 return newSVnv(tied2ptr(self)->T);
  605.         if ( !sv_cmp( key, INT2PTR(SV*,newSVpvn("labels",6) ) ) )
  606.                 return newRV_inc((SV*)(tied2ptr(self)->labels));
  607.         croak("%s not accessible for read", SvPV_nolen(key));
  608. }
  609.  
  610. SV* _som_STORE(SV* self,SV* key,SV* val) {
  611.         if ( !sv_cmp( key, INT2PTR(SV*,newSVpvn("_X",2) ) ) )
  612.                 tied2ptr(self)->X = SvIV(val);
  613.         else if ( !sv_cmp( key, INT2PTR(SV*,newSVpvn("_Y",2) ) ) )
  614.                 tied2ptr(self)->Y = SvIV(val);
  615.         else if ( !sv_cmp( key, INT2PTR(SV*,newSVpvn("_Z",2) ) ) )
  616.                 tied2ptr(self)->Z = SvIV(val);
  617.         else if ( !sv_cmp( key, INT2PTR(SV*,newSVpvn("_R",2) ) ) )
  618.                 tied2ptr(self)->R = SvNV(val);
  619.         else if ( !sv_cmp( key, INT2PTR(SV*,newSVpvn("_L0",3) ) ) )
  620.                 tied2ptr(self)->L0 = SvNV(val);
  621.         else if ( !sv_cmp( key, INT2PTR(SV*,newSVpvn("_Sigma0",7) ) ) )
  622.                 tied2ptr(self)->Sigma0 = SvNV(val);
  623.         else if ( !sv_cmp( key, INT2PTR(SV*,newSVpvn("output_dim",10) ) ) )
  624.                 tied2ptr(self)->output_dim = newSVsv(val);
  625.         else if ( !sv_cmp( key, INT2PTR(SV*,newSVpvn("LAMBDA",6) ) ) )
  626.                 tied2ptr(self)->LAMBDA = SvNV(val);
  627.         else if ( !sv_cmp( key, INT2PTR(SV*,newSVpvn("T",1) ) ) )
  628.                 tied2ptr(self)->T = SvNV(val);
  629.         else if ( !sv_cmp( key, INT2PTR(SV*,newSVpvn("map",3) ) ) )
  630.                 croak("cant assign to map");
  631.         else
  632.                 croak("%s not accessible for write", SvPV_nolen(key));
  633.         return val;
  634. }
  635.  
  636. SV* _som_FIRSTKEY() {
  637.         return INT2PTR(SV*,newSVpvn("_X",2));
  638. }
  639.  
  640. SV* _som_NEXTKEY(SV* prev) {
  641.         if ( strEQ( SvPVX(prev), "_X" ) )
  642.                 return INT2PTR(SV*,newSVpvn("_Y",2));
  643.         else if ( strEQ( SvPVX(prev), "_Y" ) )
  644.                 return INT2PTR(SV*,newSVpvn("_Z",2));
  645.         else if ( strEQ( SvPVX(prev), "_Z" ) )
  646.                 return INT2PTR(SV*,newSVpvn("_R",2));
  647.         else if ( strEQ( SvPVX(prev), "_R" ) )
  648.                 return INT2PTR(SV*,newSVpvn("_Sigma0",7));
  649.         else if ( strEQ( SvPVX(prev), "_Sigma0" ) )
  650.                 return INT2PTR(SV*,newSVpvn("_L0",3));
  651.         else if ( strEQ( SvPVX(prev), "_L0" ) )
  652.                 return INT2PTR(SV*,newSVpvn("LAMBDA",6));
  653.         else if ( strEQ( SvPVX(prev), "LAMBDA" ) )
  654.                 return INT2PTR(SV*,newSVpvn("T",1));
  655.         else if ( strEQ( SvPVX(prev), "T" ) )
  656.                 return INT2PTR(SV*,newSVpvn("labels",6));
  657.         else if ( strEQ( SvPVX(prev), "labels" ) )
  658.                 return INT2PTR(SV*,newSVpvn("map",3));
  659.         return &PL_sv_undef;
  660. }
  661.  
  662. void _som_DESTROY(SV* self) {
  663.         IV              iv;
  664.         SV              *ref;
  665.         SOM_Map         *map;
  666.         SOM_GENERIC     *som;
  667.  
  668.         if ( !SvROK(self) )
  669.                 return;
  670.         ref = SvRV(self);
  671.         if ( !SvIOK(ref) )
  672.                 return;
  673.         iv = SvIV(ref);
  674.         som = INT2PTR(SOM_GENERIC*,iv);
  675.         if ( !som )
  676.                 return;
  677.         map = som->map;
  678.         /* more to do here ? */
  679. }
  680.  
  681.  
  682.  
  683. /*
  684.  * rect functions
  685.  */
  686.  
  687. void _rect_neiguts(SOM_Rect* som,NV sigma,IV X0,IV Y0,NV* n) {
  688.         IV      x,y,X,Y;
  689.         NV      d2,s2;
  690.  
  691.         X = som->X;
  692.         Y = som->Y;
  693.  
  694.         s2 = sigma * sigma;
  695.  
  696.         for ( x=0 ; x<X ; x++ ) {
  697.                 for ( y=0 ; y<Y ; y++ ) {
  698.                         d2 = (x-X0)*(x-X0)+(y-Y0)*(y-Y0);
  699.                         if (d2 <= s2) n[x*Y+y] = sqrt(d2);
  700.                 }
  701.         }
  702. }
  703.  
  704. void _rect_new(const char* class,...) {
  705.         IV              i;
  706.         NV              sigma0,rate;
  707.         SV              *tie,*rv,*key,*val,*od,*sclass;
  708.         HV              *options,*hash,*stash;
  709.         char            *begptr,*endptr,*xstart,*ystart,*yend;
  710.         STRLEN          len;
  711.         SOM_GENERIC     *som;
  712.         dXSARGS;
  713.  
  714.         if ( (items & 1) ^ 1 )
  715.                 croak( "Weird number of arguments\n" );
  716.  
  717.         options = newHV();
  718.         for ( i=1 ; i<items ; i+=2 ) {
  719.                 key = ST(i);
  720.                 val = ST(i+1);
  721.                 len = sv_len(key);
  722.                 hv_store( options, SvPV_nolen(key), len, val, 0 );
  723.         }
  724.  
  725.         if ( !hv_exists( options, "input_dim", 9 ) )
  726.                 croak( "no input_dim argument" );
  727.         if ( !hv_exists( options, "output_dim", 10 ) )
  728.                 croak( "no output_dim argument" );
  729.  
  730.         Newxz(som,1,SOM_GENERIC);
  731.  
  732.         od = newSVsv(*hv_fetch(options,"output_dim",10,FALSE));
  733.         som->output_dim = od;
  734.  
  735.         begptr = SvPV_force(od,SvLEN(od));
  736.         endptr = SvEND(od) - 1; /* allow for terminating character */
  737.         if ( endptr < begptr )
  738.                 croak("brain damage!!!");
  739.  
  740.         xstart = begptr;
  741.         if ( !isDIGIT((char)*xstart) )
  742.                 croak("no x-dimension found");
  743.         som->X = Atol(xstart);
  744.  
  745.         ystart = yend = endptr;
  746.         if ( !isDIGIT((char)*ystart) )
  747.                 croak("no y-dimension found");
  748.         while (--ystart >= begptr)
  749.                 if ( !isDIGIT((char)*ystart) )
  750.                         break;
  751.         som->Y = Atol(++ystart);
  752.  
  753.         som->Z = SvIV(*hv_fetch(options,"input_dim",9,FALSE));
  754.  
  755.         som->R = som->X > som->Y
  756.                 ? som->Y / 2.0
  757.                 : som->X / 2.0;
  758.  
  759.         if ( hv_exists( options, "sigma0", 6 ) ) {
  760.                 sigma0 = SvNV(*hv_fetch(options,"sigma0",6,0));
  761.                 if ( sigma0 )
  762.                         som->Sigma0 = sigma0;
  763.                 else
  764.                         som->Sigma0 = som->R;
  765.         }
  766.         else
  767.                 som->Sigma0 = som->R;
  768.  
  769.         if ( hv_exists( options, "learning_rate", 13 ) ) {
  770.                 rate = SvNV(*hv_fetch(options,"learning_rate",13,0));
  771.                 if ( rate )
  772.                         som->L0 = rate;
  773.                 else
  774.                         som->L0 = 0.1;
  775.         }
  776.         else
  777.                 som->L0 = 0.1;
  778.  
  779.         som->map = _make_map(som);
  780.         som->labels = newAV();
  781.  
  782.         sclass = sv_2mortal(newSVpvf("%s",class));
  783.         if (!sv_cmp(sclass,INT2PTR(
  784.                         SV*,newSVpvn("AI::NeuralNet::FastSOM::Rect",28))))
  785.                 som->type = SOMType_Rect;
  786.         /*
  787.         else if (!sv_cmp(sclass,INT2PTR(
  788.                         SV*,newSVpvn("AI::NeuralNet::FastSOM::Hexa",28))))
  789.                 som->type = SOMType_Hexa;
  790.         */
  791.         else if (!sv_cmp(sclass,INT2PTR(
  792.                         SV*,newSVpvn("AI::NeuralNet::FastSOM::Torus",29))))
  793.                 som->type = SOMType_Torus;
  794.         else
  795.                 croak("unknown type");
  796.  
  797.         hash = (HV*)sv_2mortal((SV*)newHV());
  798.         tie = newRV_noinc(newSViv(PTR2IV(som)));
  799.         stash = gv_stashpv(class, GV_ADD);
  800.         sv_bless(tie, stash);
  801.         hv_magic(hash, (GV*)tie, PERL_MAGIC_tied);
  802.         rv = sv_bless(newRV_noinc((SV*)hash),stash);
  803.  
  804.         som->ref = rv;
  805.  
  806.         /*
  807.          * here 'hash' is the object seen from the perl side.
  808.          * 'tie' is what we see from the c side when accessing the tied
  809.          * functionality.
  810.          */
  811.  
  812.         sp = mark;
  813.         XPUSHs(rv);
  814.         PUTBACK;
  815. }
  816.  
  817. SV* _rect_radius(SV* self) {
  818.         MAGIC           *mg;
  819.         SOM_GENERIC     *som;
  820.  
  821.         if ( !(mg = selfmagic(self)) )
  822.                 croak("self has no magic!\n");
  823.         som = self2somptr(self,mg);
  824.  
  825.         return newSVnv(som->R);
  826. }
  827.  
  828.  
  829.  
  830. /*
  831.  * torus functions
  832.  */
  833.  
  834. void _torus_neiguts(SOM_Torus* som,NV sigma,IV X0,IV Y0,NV* n) {
  835.         IV      x,y,X,Y;
  836.         NV      d2,s2;
  837.  
  838.         X = som->X;
  839.         Y = som->Y;
  840.  
  841.         s2 = sigma * sigma;
  842.  
  843.         for ( x=0 ; x<X ; x++ ) {
  844.                 for ( y=0 ; y<Y ; y++ ) {
  845.  
  846.                         /*
  847.                          * which one of these should "win"?
  848.                          */
  849.  
  850.                         d2 = (x-X0)*(x-X0) + (y-Y0)*(y-Y0);
  851.                         if (d2 <= s2) n[x*Y+y] = sqrt(d2);
  852.  
  853.                         d2 = (x-X-X0)*(x-X-X0) + (y-Y0)*(y-Y0);
  854.                         if (d2 <= s2) n[x*Y+y] = sqrt(d2);
  855.  
  856.                         d2 = (x+X-X0)*(x+X-X0) + (y-Y0)*(y-Y0);
  857.                         if (d2 <= s2) n[x*Y+y] = sqrt(d2);
  858.  
  859.                         d2 = (x-X0)*(x-X0) + (y-Y-Y0)*(y-Y-Y0);
  860.                         if (d2 <= s2) n[x*Y+y] = sqrt(d2);
  861.  
  862.                         d2 = (x-X0)*(x-X0) + (y+Y-Y0)*(y+Y-Y0);
  863.                         if (d2 <= s2) n[x*Y+y] = sqrt(d2);
  864.                 }
  865.         }
  866. }
  867.  
  868. /* http://www.ai-junkie.com/ann/som/som3.html */
  869.  
  870.  
  871.  
  872. /*
  873.  * hexa functions
  874.  */
  875.  
  876. void _hexa_new(const char* class) {
  877.         IV              i;
  878.         SV              *key,*val,*od,*tie,*rv;
  879.         NV              sigma0,rate;
  880.         HV              *options,*hash,*stash;
  881.         STRLEN          len;
  882.         SOM_Hexa        *hexa;
  883.         dXSARGS;
  884.  
  885.         if ( (items & 1) ^ 1 )
  886.                 croak( "Weird number of arguments\n" );
  887.  
  888.         options = newHV();
  889.         for ( i=1 ; i<items ; i+=2 ) {
  890.                 key = ST(i);
  891.                 val = ST(i+1);
  892.                 len = sv_len(key);
  893.                 hv_store( options, SvPV_nolen(key), len, val, 0 );
  894.         }
  895.  
  896.         if ( !hv_exists( options, "input_dim", 9 ) )
  897.                 croak( "no input_dim argument" );
  898.         if ( !hv_exists( options, "output_dim", 10 ) )
  899.                 croak( "no ouput_dim argument" );
  900.  
  901.         Newxz(hexa,1,SOM_Hexa);
  902.  
  903.         od = newSVsv(*hv_fetch(options,"output_dim",10,FALSE));
  904.         hexa->output_dim = od;
  905.  
  906.         hexa->X=SvIV(*hv_fetch(options,"output_dim",10,FALSE));
  907.         hexa->Z=SvIV(*hv_fetch(options,"input_dim",9,FALSE));
  908.  
  909.         hexa->Y = hexa->X;
  910.         hexa->R = hexa->X / 2.0;
  911.  
  912.         if ( hv_exists( options, "sigma0", 6 ) ) {
  913.                 sigma0 = SvNV(*hv_fetch(options,"sigma0",6,0));
  914.                 if ( sigma0 )
  915.                         hexa->Sigma0 = sigma0;
  916.                 else
  917.                         hexa->Sigma0 = hexa->R;
  918.         }
  919.         else
  920.                 hexa->Sigma0 = hexa->R;
  921.  
  922.         if ( hv_exists( options, "learning_rate", 13 ) ) {
  923.                 rate = SvNV(*hv_fetch(options,"learning_rate",13,0));
  924.                 if ( rate )
  925.                         hexa->L0 = rate;
  926.                 else
  927.                         hexa->L0 = 0.1;
  928.         }
  929.         else
  930.                 hexa->L0 = 0.1;
  931.  
  932.         hexa->map = _make_map( hexa );
  933.         hexa->labels = newAV();
  934.  
  935.         hexa->type = SOMType_Hexa;
  936.  
  937.         hash = (HV*)sv_2mortal((SV*)newHV());
  938.         tie = newRV_noinc(newSViv(PTR2IV(hexa)));
  939.         stash = gv_stashpv(class, GV_ADD);
  940.         sv_bless(tie, stash);
  941.         hv_magic(hash, (GV*)tie, PERL_MAGIC_tied);
  942.         rv = sv_bless(newRV_noinc((SV*)hash),stash);
  943.  
  944.         hexa->ref = rv;
  945.  
  946.         sp = mark;
  947.         XPUSHs(rv);
  948.         PUTBACK;
  949. }
  950.  
  951. NV _hexa_distance(NV x1,NV y1,NV x2,NV y2) {
  952.         NV      tmp,dx,dy;
  953.  
  954.         if ( x1+y1 > x2+y2 ) {
  955.                 tmp=x1; x1=x2; x2=tmp;
  956.                 tmp=y1; y1=y2; y2=tmp;
  957.         }
  958.  
  959.         dx = x2 - x1;
  960.         dy = y2 - y1;
  961.  
  962.         if ( dx<0 || dy<0 )
  963.                 return abs(dx) + abs(dy);
  964.         else
  965.                 return dx<dy ? dy : dx;
  966. }
  967.  
  968. void _hexa_neiguts(SOM_Hexa* som,NV sigma,IV X0,IV Y0,NV* n) {
  969.         IV      x,y,X,Y;
  970.         NV      d;
  971.  
  972.         X = som->X;
  973.         Y = som->Y;
  974.  
  975.         for ( x=0 ; x<X ; x++ ) {
  976.                 for ( y=0 ; y<Y ; y++ ) {
  977.                         d = _hexa_distance(X0,Y0,x,y);
  978.                         if (d <= sigma) n[x*Y+y] = d;
  979.                 }
  980.         }
  981. }
  982.  
  983.  
  984.  
  985. /*
  986.  * map functions
  987.  */
  988.  
  989. SV* _map_FETCH(SV* self,I32 x) {
  990.         SOM_Map         *map;
  991.         SOM_Array       *array;
  992.        
  993.         map = INT2PTR(SOM_Map*,self2iv(self));
  994.         array = (&map->array)[x];
  995.         SvREFCNT_inc(array->ref);
  996.         return array->ref;
  997. }
  998.  
  999. void _map_DESTROY(SV* self) {
  1000.         SOM_Map         *map;
  1001.  
  1002.         map = INT2PTR(SOM_Map*,self2iv(self));
  1003.         /* need more done here ? */
  1004.         Safefree( map );
  1005. }
  1006.  
  1007.  
  1008.  
  1009. /*
  1010.  * array functions
  1011.  */
  1012.  
  1013. void _array_STORE(SV* self,IV y,SV* aref) {
  1014.         I32             len;
  1015.         NV              tmp;
  1016.         AV              *src;
  1017.         SV              **ptr;
  1018.         SOM_Array       *array;
  1019.         SOM_Vector      *dst;
  1020.  
  1021.         if ( SvTYPE( SvRV(aref) ) != SVt_PVAV )
  1022.                 croak("value to store is not a reference to an array\n");
  1023.         src = (AV*)SvRV( aref );
  1024.  
  1025.         array = INT2PTR(SOM_Array*,self2iv(self));
  1026.         dst = (&array->vector)[y];
  1027.  
  1028.         if ( y < 0 )
  1029.                 croak("storing y-index < 0 not supported\n");
  1030.         if ( y >= array->Y )
  1031.                 croak("storing y-index > y-dimension of SOM\n");
  1032.  
  1033.         len = av_len( src );
  1034.         if ( len < 0 )
  1035.                 croak("cant store empty vector\n");
  1036.         if ( len+1 > array->Z )
  1037.                 croak("vector too long\n");
  1038.         if ( len+1 < array->Z )
  1039.                 croak("vector too short\n");
  1040.  
  1041.         for ( ; len >= 0 ; len-- ) {
  1042.                 ptr = av_fetch( src, len, 0 );
  1043.                 if ( ptr == NULL )
  1044.                         croak("NULL ptr!\n");
  1045.                 tmp = SvNV(*ptr);
  1046.                 (&dst->element)[len] = tmp;
  1047.         }
  1048. }
  1049.  
  1050. SV* _array_FETCH(SV* self,I32 y) {
  1051.         SOM_Array       *array;
  1052.         SOM_Vector      *vector;
  1053.  
  1054.         array = INT2PTR(SOM_Array*,self2iv(self));
  1055.         vector = (&array->vector)[y];
  1056.         SvREFCNT_inc(vector->ref);
  1057.         return vector->ref;
  1058. }
  1059.  
  1060. void _array_DESTROY(SV* self) {
  1061.         SOM_Array       *array;
  1062.  
  1063.         array = INT2PTR(SOM_Array*,self2iv(self));
  1064.         /* need more done here ? */
  1065.         Safefree( array );
  1066. }
  1067.  
  1068.  
  1069.  
  1070. /*
  1071.  * vector functions
  1072.  */
  1073.  
  1074. void _vector_STORE(SV* self,I32 z,NV val) {
  1075.         SOM_Vector      *vector;
  1076.  
  1077.         vector = INT2PTR(SOM_Vector*,self2iv(self));
  1078.         if ( z < 0 )
  1079.                 croak("negative z-index not supported\n");
  1080.         if ( z >= vector->Z )
  1081.                 croak("z-index larger than vector dimension\n");
  1082.         (&vector->element)[z] = val;
  1083. }
  1084.  
  1085. SV* _vector_FETCH(SV* self,I32 z) {
  1086.         SOM_Vector      *vector;
  1087.  
  1088.         vector = INT2PTR(SOM_Vector*,self2iv(self));
  1089.         return newSVnv((&vector->element)[z]);
  1090. }
  1091.  
  1092. void _vector_DESTROY(SV* self) {
  1093.         SOM_Vector      *vector;
  1094.  
  1095.         vector = INT2PTR(SOM_Vector*,self2iv(self));
  1096.         /* need more done here ? */
  1097.         Safefree( vector );
  1098. }
  1099.  
  1100.  
  1101.  
  1102. /*
  1103.  *
  1104.  * End of C code. Begin XS.
  1105.  *
  1106.  */
  1107.  
  1108.  
  1109.  
  1110. MODULE = AI::NeuralNet::FastSOM         PACKAGE = AI::NeuralNet::FastSOM       
  1111.  
  1112. PROTOTYPES: DISABLE
  1113.  
  1114.  
  1115. void
  1116. train (self, epochs, ...)
  1117.         SV *    self
  1118.         IV      epochs
  1119.         PREINIT:
  1120.         I32* temp;
  1121.         temp = PL_markstack_ptr++;
  1122.         _som_train(self,epochs);
  1123.         if (PL_markstack_ptr != temp) {
  1124.                 PL_markstack_ptr = temp;
  1125.                 XSRETURN_EMPTY;
  1126.         }
  1127.         return;
  1128.  
  1129. void
  1130. bmu (self, sample)
  1131.         SV *    self
  1132.         AV *    sample
  1133.         PREINIT:
  1134.         I32* temp;
  1135.         PPCODE:
  1136.         temp = PL_markstack_ptr++;
  1137.         _som_bmu(self,sample);
  1138.         if (PL_markstack_ptr != temp) {
  1139.                 PL_markstack_ptr = temp;
  1140.                 XSRETURN_EMPTY;
  1141.         }
  1142.         return;
  1143.  
  1144. SV *
  1145. map (self)
  1146.         SV *    self
  1147.         PREINIT:
  1148.         SV* rv;
  1149.         CODE:
  1150.         rv = _som_map(self);
  1151.         ST(0) = rv;
  1152.         sv_2mortal(ST(0));
  1153.  
  1154. SV *
  1155. output_dim (self)
  1156.         SV *    self
  1157.         PREINIT:
  1158.         SV* rv;
  1159.         CODE:
  1160.         rv = _som_output_dim(self);
  1161.         ST(0) = rv;
  1162.         sv_2mortal(ST(0));
  1163.  
  1164. void
  1165. _adjust (self, l, sigma, unit, v)
  1166.         SV *    self
  1167.         NV      l
  1168.         NV      sigma
  1169.         AV *    unit
  1170.         AV *    v
  1171.         PREINIT:
  1172.         I32* temp;
  1173.         PPCODE:
  1174.         temp = PL_markstack_ptr++;
  1175.         _adjust(self, l, sigma, unit, v);
  1176.         if (PL_markstack_ptr != temp) {
  1177.                 PL_markstack_ptr = temp;
  1178.                 XSRETURN_EMPTY;
  1179.         }
  1180.         return;
  1181.  
  1182. void
  1183. STORABLE_freeze (self, cloning)
  1184.         SV *    self
  1185.         SV *    cloning
  1186.         PREINIT:
  1187.         I32* temp;
  1188.         PPCODE:
  1189.         temp = PL_markstack_ptr++;
  1190.         _som_FREEZE(self,cloning);
  1191.         if (PL_markstack_ptr != temp) {
  1192.                 PL_markstack_ptr = temp;
  1193.                 XSRETURN_EMPTY;
  1194.         }
  1195.         return;
  1196.  
  1197. void
  1198. STORABLE_thaw (self, cloning, serialized, ...)
  1199.         SV *    self
  1200.         SV *    cloning
  1201.         SV *    serialized
  1202.         PREINIT:
  1203.         I32* temp;
  1204.         PPCODE:
  1205.         temp = PL_markstack_ptr++;
  1206.         _som_THAW(self,cloning,serialized);
  1207.         if (PL_markstack_ptr != temp) {
  1208.                 PL_markstack_ptr = temp;
  1209.                 XSRETURN_UNDEF;
  1210.         }
  1211.         return;
  1212.  
  1213. SV *
  1214. FETCH (self, key)
  1215.         SV *    self
  1216.         SV *    key
  1217.         PREINIT:
  1218.         SV* rv;
  1219.         CODE:
  1220.         rv = _som_FETCH(self, key);
  1221.         ST(0) = rv;
  1222.         sv_2mortal(ST(0));
  1223.  
  1224. void
  1225. STORE (self, key, val)
  1226.         SV *    self
  1227.         SV *    key
  1228.         SV *    val
  1229.         PREINIT:
  1230.         I32* temp;
  1231.         PPCODE:
  1232.         temp = PL_markstack_ptr++;
  1233.         _som_STORE(self, key, val);
  1234.         if (PL_markstack_ptr != temp) {
  1235.                 PL_markstack_ptr = temp;
  1236.                 XSRETURN_EMPTY;
  1237.         }
  1238.         return;
  1239.  
  1240. SV *
  1241. FIRSTKEY (self)
  1242.         SV *    self
  1243.         PREINIT:
  1244.         SV* rv;
  1245.         CODE:
  1246.         if (!self) croak("avoiding -Wextra");
  1247.         rv = _som_FIRSTKEY();
  1248.         ST(0) = rv;
  1249.         sv_2mortal(ST(0));
  1250.  
  1251. SV *
  1252. NEXTKEY (self,prev)
  1253.         SV *    self
  1254.         SV *    prev
  1255.         PREINIT:
  1256.         SV* rv;
  1257.         CODE:
  1258.         if (!self) croak("avoiding -Wextra");
  1259.         rv = _som_NEXTKEY(prev);
  1260.         ST(0) = rv;
  1261.         sv_2mortal(ST(0));
  1262.  
  1263. void
  1264. DESTROY (obj)
  1265.         SV *    obj
  1266.         PREINIT:
  1267.         I32* temp;
  1268.         PPCODE:
  1269.         temp = PL_markstack_ptr++;
  1270.         _som_DESTROY(obj);
  1271.         if (PL_markstack_ptr != temp) {
  1272.                 PL_markstack_ptr = temp;
  1273.                 XSRETURN_EMPTY;
  1274.         }
  1275.         return;
  1276.  
  1277.  
  1278.  
  1279. MODULE = AI::NeuralNet::FastSOM         PACKAGE = AI::NeuralNet::FastSOM::Rect 
  1280.  
  1281. PROTOTYPES: DISABLE
  1282.  
  1283.  
  1284. void
  1285. new (class, ...)
  1286.         const char *    class
  1287.         PREINIT:
  1288.         I32* temp;
  1289.         PPCODE:
  1290.         temp = PL_markstack_ptr++;
  1291.         _rect_new(class);
  1292.         if (PL_markstack_ptr != temp) {
  1293.                 PL_markstack_ptr = temp;
  1294.                 XSRETURN_EMPTY;
  1295.         }
  1296.         return;
  1297.  
  1298. AV *
  1299. neighbors (self, sigma, X, Y, ...)
  1300.         SV *    self
  1301.         NV      sigma
  1302.         IV      X
  1303.         IV      Y
  1304.         PREINIT:
  1305.         I32* temp;
  1306.         CODE:
  1307.         temp = PL_markstack_ptr++;
  1308.         RETVAL = _neighbors(self, sigma, X, Y);
  1309.         PL_markstack_ptr = temp;
  1310.         OUTPUT:
  1311.         RETVAL
  1312.  
  1313. SV *
  1314. radius (self)
  1315.         SV *    self
  1316.         PREINIT:
  1317.         SV* rv;
  1318.         CODE:
  1319.         rv = _rect_radius(self);
  1320.         ST(0) = rv;
  1321.         sv_2mortal(ST(0));
  1322.  
  1323.  
  1324.  
  1325.  
  1326. MODULE = AI::NeuralNet::FastSOM         PACKAGE = AI::NeuralNet::FastSOM::Torus
  1327.  
  1328. PROTOTYPES: DISABLE
  1329.  
  1330.  
  1331. AV *
  1332. neighbors (self, sigma, X, Y, ...)
  1333.         SV *    self
  1334.         NV      sigma
  1335.         IV      X
  1336.         IV      Y
  1337.         PREINIT:
  1338.         I32* temp;
  1339.         CODE:
  1340.         temp = PL_markstack_ptr++;
  1341.         RETVAL = _neighbors(self, sigma, X, Y);
  1342.         PL_markstack_ptr = temp;
  1343.         OUTPUT:
  1344.         RETVAL
  1345.  
  1346.  
  1347.  
  1348. MODULE = AI::NeuralNet::FastSOM         PACKAGE = AI::NeuralNet::FastSOM::Hexa 
  1349.  
  1350. PROTOTYPES: DISABLE
  1351.  
  1352.  
  1353. void
  1354. new (class, ...)
  1355.         const char *    class
  1356.         PREINIT:
  1357.         I32* temp;
  1358.         PPCODE:
  1359.         temp = PL_markstack_ptr++;
  1360.         _hexa_new(class);
  1361.         if (PL_markstack_ptr != temp) {
  1362.                 PL_markstack_ptr = temp;
  1363.                 XSRETURN_EMPTY;
  1364.         }
  1365.         return;
  1366.  
  1367. AV *
  1368. neighbors (self, sigma, X, Y, ...)
  1369.         SV *    self
  1370.         NV      sigma
  1371.         IV      X
  1372.         IV      Y
  1373.         PREINIT:
  1374.         I32* temp;
  1375.         CODE:
  1376.         temp = PL_markstack_ptr++;
  1377.         RETVAL = _neighbors(self, sigma, X, Y);
  1378.         PL_markstack_ptr = temp;
  1379.         OUTPUT:
  1380.         RETVAL
  1381.  
  1382.  
  1383.  
  1384. MODULE = AI::NeuralNet::FastSOM         PACKAGE = AI::NeuralNet::FastSOM::Utils
  1385.  
  1386. PROTOTYPES: DISABLE
  1387.  
  1388.  
  1389. NV
  1390. vector_distance (V1, V2)
  1391.         AV_SPECIAL*     V1;
  1392.         AV_SPECIAL*     V2;
  1393.         PREINIT:
  1394.         NV rv;
  1395.         CODE:
  1396.         rv = _vector_distance((AV*)V1, (AV*)V2);
  1397.         XSprePUSH; PUSHn((NV)rv);
  1398.  
  1399.  
  1400.  
  1401. MODULE = AI::NeuralNet::FastSOM         PACKAGE = AI::NeuralNet::FastSOM::MAP  
  1402.  
  1403. PROTOTYPES: DISABLE
  1404.  
  1405.  
  1406. SV *
  1407. FETCH (self, x)
  1408.         SV *    self
  1409.         I32     x
  1410.         PREINIT:
  1411.         SV* rv;
  1412.         CODE:
  1413.         rv = _map_FETCH(self, x);
  1414.         ST(0) = rv;
  1415.         sv_2mortal(ST(0));
  1416.  
  1417. IV
  1418. FETCHSIZE (self)
  1419.         SV *    self
  1420.         PREINIT:
  1421.         IV rv;
  1422.         CODE:
  1423.         rv = (INT2PTR(SOM_Map*,self2iv(self)))->X;
  1424.         XSprePUSH; PUSHi((IV)rv);
  1425.  
  1426. void
  1427. DESTROY (obj)
  1428.         SV *    obj
  1429.         PREINIT:
  1430.         I32* temp;
  1431.         PPCODE:
  1432.         temp = PL_markstack_ptr++;
  1433.         _map_DESTROY(obj);
  1434.         if (PL_markstack_ptr != temp) {
  1435.                 PL_markstack_ptr = temp;
  1436.                 XSRETURN_EMPTY;
  1437.         }
  1438.         return;
  1439.  
  1440.  
  1441.  
  1442. MODULE = AI::NeuralNet::FastSOM         PACKAGE = AI::NeuralNet::FastSOM::ARRAY
  1443.  
  1444. PROTOTYPES: DISABLE
  1445.  
  1446.  
  1447. void
  1448. STORE (self, y, aref)
  1449.         SV *    self
  1450.         IV      y
  1451.         SV *    aref
  1452.         PREINIT:
  1453.         I32* temp;
  1454.         PPCODE:
  1455.         temp = PL_markstack_ptr++;
  1456.         _array_STORE(self, y, aref);
  1457.         if (PL_markstack_ptr != temp) {
  1458.                 PL_markstack_ptr = temp;
  1459.                 XSRETURN_EMPTY;
  1460.         }
  1461.         return;
  1462.  
  1463. SV *
  1464. FETCH (self, y)
  1465.         SV *    self
  1466.         I32     y
  1467.         PREINIT:
  1468.         SV* rv;
  1469.         CODE:
  1470.         rv = _array_FETCH(self, y);
  1471.         ST(0) = rv;
  1472.         sv_2mortal(ST(0));
  1473.  
  1474. IV
  1475. FETCHSIZE (self)
  1476.         SV *    self
  1477.         PREINIT:
  1478.         IV rv;
  1479.         CODE:
  1480.         rv = (INT2PTR(SOM_Array*,self2iv(self)))->Y;
  1481.         XSprePUSH; PUSHi((IV)rv);
  1482.  
  1483. void
  1484. DESTROY (obj)
  1485.         SV *    obj
  1486.         PREINIT:
  1487.         I32* temp;
  1488.         PPCODE:
  1489.         temp = PL_markstack_ptr++;
  1490.         _array_DESTROY(obj);
  1491.         if (PL_markstack_ptr != temp) {
  1492.                 PL_markstack_ptr = temp;
  1493.                 XSRETURN_EMPTY;
  1494.         }
  1495.         return;
  1496.  
  1497.  
  1498.  
  1499. MODULE = AI::NeuralNet::FastSOM PACKAGE = AI::NeuralNet::FastSOM::VECTOR       
  1500.  
  1501. PROTOTYPES: DISABLE
  1502.  
  1503.  
  1504. void
  1505. STORE (self, z, val)
  1506.         SV *    self
  1507.         I32     z
  1508.         NV      val
  1509.         PREINIT:
  1510.         I32* temp;
  1511.         PPCODE:
  1512.         temp = PL_markstack_ptr++;
  1513.         _vector_STORE(self, z, val);
  1514.         if (PL_markstack_ptr != temp) {
  1515.                 PL_markstack_ptr = temp;
  1516.                 XSRETURN_EMPTY;
  1517.         }
  1518.         return;
  1519.  
  1520. SV *
  1521. FETCH (self, z)
  1522.         SV *    self
  1523.         I32     z
  1524.         PREINIT:
  1525.         SV* rv;
  1526.         CODE:
  1527.         rv = _vector_FETCH(self, z);
  1528.         ST(0) = rv;
  1529.         sv_2mortal(ST(0));
  1530.  
  1531. IV
  1532. FETCHSIZE (self)
  1533.         SV *    self
  1534.         PREINIT:
  1535.         IV rv;
  1536.         CODE:
  1537.         rv = (INT2PTR(SOM_Vector*,self2iv(self)))->Z;
  1538.         XSprePUSH; PUSHi((IV)rv);
  1539.  
  1540. void
  1541. DESTROY (obj)
  1542.         SV *    obj
  1543.         PREINIT:
  1544.         I32* temp;
  1545.         PPCODE:
  1546.         temp = PL_markstack_ptr++;
  1547.         _vector_DESTROY(obj);
  1548.         if (PL_markstack_ptr != temp) {
  1549.                 PL_markstack_ptr = temp;
  1550.                 XSRETURN_EMPTY;
  1551.         }
  1552.         return;
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top