hmops.c

Go to the documentation of this file.
00001 /*
00002  *  hmdops_new.c
00003  *
00004  *  PURPOSE
00005  *     codes to accelerate scilab hypermatrices operations
00006  *     like extraction / insertion / creation
00007  *
00008  *  AUTHOR
00009  *     Bruno Pincon (Bruno.Pincon@iecn.u-nancy.fr)
00010  *
00011  *  exportation de C2F(ishm)
00012  *                 C2F(intehm)
00013  *                 C2F(intihm)
00014  *  modifications pour le champs dim en int32 maintenant
00015  */
00016 
00017 
00018 #include <math.h>
00019 #include <stdlib.h>
00020 #include "stack-c.h"
00021 #include "stack2.h"
00022 #include "hmops.h"
00023 
00024 #ifdef _MSC_VER
00025 #undef min
00026 #undef max
00027 #endif
00028 #define min(a,b) ((a) < (b) ? (a) : (b))
00029 #define max(a,b) ((a) < (b) ? (b) : (a))
00030 #define sign(a) ((a) < 0 ? -1 : 1)
00031 
00032 #define SCI_REAL_OR_CMPLX 1
00033 #define SCI_POLYNOMIAL 2
00034 #define SCI_IMPLICIT_POLY 129
00035 #define SCI_BOOLEAN 4
00036 #define SCI_SP_BOOLEAN 6
00037 #define SCI_INTEGER 8
00038 #define SCI_STRING 10
00039 #define SCI_MLIST 17
00040 #define SCI_INT8 1
00041 #define SCI_UINT8 11
00042 #define SCI_INT16 2
00043 #define SCI_UINT16 12
00044 #define SCI_INT32 4
00045 #define SCI_UINT32 14
00046 #define NOT_REAL_or_CMPLX_or_BOOL_or_INT -1
00047 #define OLD_HYPERMAT -2
00048 
00049 
00050 typedef struct hypermat {
00051   int type;           /* type of the (elements of the) hyper matrix */
00052   int it;             /* sub type (in case of type=1 or type=8) */
00053   int dimsize;        /* number of dimensions of the hyper matrix */
00054   int size;           /* total number of elements : size = dims[0]x... x dims[dimsize-1] */
00055   int *dims;          /* number of elements in each dimension */
00056   double *R, *I;      /* in case of type=1 points to the elements (I being used if it=1)  */
00057   void *P;            /* in case of type=4 or 8 points to the elements */
00058 } HyperMat;
00059 
00060 typedef struct sci_bool_sparse {
00061   int m;
00062   int n;
00063   int nel;
00064   int *mnel;
00065   int *jcol;
00066 } SciBoolSparse;
00067 
00068 
00069 
00070 extern int C2F(ddmpev)();
00071 #ifdef _MSC_VER
00072 int C2F(createlistcvarfrom)();
00073 #endif
00074 
00075 extern int C2F(tpconv)(integer *xtyp, integer *ytyp, integer *n, void *dx, integer *incx, void *dy, integer *incy);
00076 
00077 static int get_length(int num)
00078 {
00079   int il;
00080   il = iadr(*Lstk( num + Top - Rhs ));
00081   return(*istk(il+1));
00082 }
00083 
00084 static void get_length_and_pointer(int num, int *n, int **t)
00085 {
00086   int il;
00087   il = iadr(*Lstk( num + Top - Rhs ));
00088   *n = *istk(il+1);
00089   *t = istk(il+4);
00090 }
00091 
00092 #define GetHMat(pos,H) if (! get_hmat(pos,H)) { return 0;}
00093  
00094 static int get_hmat(int num, HyperMat *H)
00095 {
00096   int il, il1, il2, il3,/* it,*/ lw;
00097 
00098   lw = num + Top - Rhs;
00099   il = iadr(*Lstk( lw )); 
00100   if ( *istk(il) < 0 )
00101     il = iadr(*istk(il+1));
00102           
00103   if ( *istk(il) != SCI_MLIST )
00104     return 0;
00105   else if ( *istk(il+1) != 3 )  /* a hm mlist must have 3 fields */
00106     return 0;
00107 
00108   /*  get the pointers for the 3 fields */
00109   il1 = sadr(il+6);
00110   il2 = il1 + *istk(il+3) - 1;
00111   il3 = il1 + *istk(il+4) - 1;
00112   il1 = iadr(il1); il2 = iadr(il2); il3 = iadr(il3);
00113 
00114   /*  test if the first field is a matrix string with 3 components
00115    *  and that the first is "hm" (ie 17 22  in scilab char code)
00116    */
00117   if ( (*istk(il1) != SCI_STRING)  |  ((*istk(il1+1))*(*istk(il1+2)) != 3)  )
00118     return 0;
00119   else if ( *istk(il1+5)-1 != 2 )  /* 1 str must have 2 chars */
00120     return 0;
00121   else if ( *istk(il1+8) != 17  || *istk(il1+9) != 22 )
00122     return 0;
00123 
00124 
00125   /*  get the 2d field */
00126   if ( *istk(il2) == SCI_REAL_OR_CMPLX  &&  *istk(il2+3) == 0 )
00127     { 
00128       /* this is an old hypermat (the dim field is an array of doubles) */
00129       H->type = OLD_HYPERMAT;
00130       H->it = -1; H->size = -1;
00131       H->P = (void *) istk(il3);
00132       return 2;
00133     }
00134 
00135   if ( (*istk(il2) != SCI_INTEGER)  |  (*istk(il2+3) != SCI_INT32) )
00136     return 0;
00137 
00138 
00139   H->dimsize = (*istk(il2+1))*(*istk(il2+2));
00140   H->dims = istk(il2+4);
00141 
00142   /* needed for Jpc stuff (putlhsvar) */
00143   Nbvars = Max(Nbvars,num);
00144   C2F(intersci).ntypes[num-1] = '$';
00145   C2F(intersci).iwhere[num-1] = *Lstk(lw);
00146   C2F(intersci).lad[num-1] = 0;  /* a voir ? */
00147 
00148   /*  get the 3d field */
00149   switch ( *istk(il3) )
00150     {
00151     case (SCI_REAL_OR_CMPLX):
00152       H->size = (*istk(il3+1))*(*istk(il3+2));
00153       H->type = SCI_REAL_OR_CMPLX;
00154       H->it = *istk(il3+3);
00155       H->R = stk(sadr(il3+4));
00156       if ( H->it == 1 )
00157         H->I = H->R + H->size;
00158       return 1;
00159 
00160     case (SCI_BOOLEAN):
00161       H->size = (*istk(il3+1))*(*istk(il3+2));
00162       H->type = SCI_BOOLEAN;
00163       H->it = 0;   /* not used */
00164       H->P = (void *) istk(il3+3);
00165       return 1;
00166 
00167     case (SCI_INTEGER):
00168       H->size = (*istk(il3+1))*(*istk(il3+2));
00169       H->type = SCI_INTEGER;
00170       H->it = *istk(il3+3);
00171       H->P = (void *) istk(il3+4);
00172       return 1;
00173 
00174     default:
00175       H->type = NOT_REAL_or_CMPLX_or_BOOL_or_INT;
00176       H->it = -1; H->size = -1;
00177       H->P = (void *) istk(il3);
00178       return 2;
00179     }
00180 }      
00181  
00182 int C2F(ishm)()
00183 {
00184   /* teste si l'argument en Top est une hypermatrice */
00185   int il, il1, il2;
00186   il = iadr(*Lstk( Top )); 
00187   if ( *istk(il) < 0 )
00188     il = iadr(*istk(il+1));
00189           
00190   if ( *istk(il) != SCI_MLIST )
00191     return 0;
00192   else if ( *istk(il+1) != 3 )  /* a hm mlist must have 3 fields */
00193     return 0;
00194 
00195   /*  get the pointer of the first and second fields */
00196   il1 = sadr(il+6);
00197   il2 = il1 + *istk(il+3) - 1;
00198   il1 = iadr(il1); il2 = iadr(il2);
00199 
00200   /*  test if the first field is a matrix string with 3 components
00201    *  and that the first is "hm" (ie 17 22  in scilab char code)
00202    */
00203   if ( (*istk(il1) != SCI_STRING)  |  ((*istk(il1+1))*(*istk(il1+2)) != 3)  )
00204     return 0;
00205   else if ( *istk(il1+5)-1 != 2 )  /* 1 str must have 2 chars */
00206     return 0;
00207   else if ( *istk(il1+8) != 17  || *istk(il1+9) != 22 )
00208     return 0;
00209 
00210   return 1;
00211 }      
00212 
00213 static int get_mat_as_hmat(int num, HyperMat *H)
00214 {
00215   int il, type, lw;
00216   static int dims[2];
00217 
00218   lw = num + Top - Rhs;
00219   il = iadr(*Lstk( lw )); 
00220   if ( *istk(il) < 0 )
00221     il = iadr(*istk(il+1));
00222         
00223   type = *istk(il);
00224 
00225   if (type == SCI_REAL_OR_CMPLX || type == SCI_BOOLEAN || type == SCI_INTEGER)
00226     {
00227 
00228       /* needed for Jpc stuff (putlhsvar) ? */
00229       Nbvars = Max(Nbvars,num);
00230       C2F(intersci).ntypes[num-1] = '$';
00231       C2F(intersci).iwhere[num-1] = *Lstk(lw);
00232       C2F(intersci).lad[num-1] = 0;  /* a voir ? */
00233 
00234       H->type = type;
00235       H->dimsize = 2;
00236       dims[0] = *istk(il+1); 
00237       dims[1] = *istk(il+2);
00238       H->size = dims[0]*dims[1];
00239       H->dims = dims;
00240       if (type == SCI_REAL_OR_CMPLX)
00241         {
00242           H->it = *istk(il+3);
00243           H->R = stk(sadr(il+4));
00244           if (H->it == 1)
00245             H->I = H->R + H->size;
00246         }
00247       else if (type == SCI_BOOLEAN)
00248         {
00249           H->it = 0;
00250           H->P = (void *) istk(il+3);
00251         }
00252       else /* type = SCI_INTEGER */
00253         {
00254           H->it = *istk(il+3);
00255           H->P = (void *) istk(il+4);
00256         }
00257       return 1;
00258     }
00259     else
00260       return 0;
00261 }
00262 
00263 #define CreateHMat(pos,H) if (! cre_hmat(pos,H)) { return 0;}
00264 
00265 static int cre_hmat(int pos, HyperMat *H)
00266 {
00267   /*  dans cette version, seuls les champs dimsize, size et it sont definis
00268    *  et on alloue alors la memoire des champs dims, R (et I si it=1) dans
00269    *  la pile scilab (juste � la place occupee par la variable).
00270    */
00271   static char *Str[]= { "hm","dims","entries"}; int m1=1,n1=3;
00272   int mL=3,nL=1,lL, one=1, lr, lc, lar, lac;
00273   CreateVar(pos,"m", &mL, &nL, &lL);
00274   CreateListVarFromPtr(pos,1,"S", &m1, &n1, Str);
00275   lr = 4; lar = -1;
00276   CreateListVarFrom(pos,2,"I", &one, &H->dimsize, &lr, &lar);
00277   H->dims = istk(lr);
00278 
00279   lar = -1; lac = -1;
00280 
00281   switch (H->type)
00282     {
00283     case (SCI_REAL_OR_CMPLX):
00284       CreateListCVarFrom(pos,3,"d", &H->it, &H->size, &one , &lr, &lc, &lar, &lac);
00285       H->R = stk(lr);
00286       if ( H->it == 1)
00287         H->I = stk(lc);
00288       return 1;
00289       
00290     case (SCI_BOOLEAN):
00291       CreateListVarFrom(pos, 3, "b", &H->size, &one, &lr, &lar);
00292       H->P = (void *) istk(lr);
00293       return 1;
00294 
00295     case (SCI_INTEGER):
00296       lr = H->it;
00297       CreateListVarFrom(pos, 3, "I", &H->size, &one, &lr, &lar);
00298       H->P = (void *) istk(lr);
00299       return 1;
00300     }
00301 
00302         /* Ajout Allan CORNET Correction Warning */
00303         /* warning C4715: 'cre_hmat' : not all control paths return a value */
00304         return 1;
00305         
00306 
00307 }
00308 
00309 
00310 #define GetSciBoolSparse(pos,M) if (! get_sci_bool_sparse(pos,M)) { return 0;}
00311 
00312 static int get_sci_bool_sparse(int num, SciBoolSparse *M)
00313 {
00314   int il, lw;
00315 
00316   lw = num + Top - Rhs;
00317   il = iadr(*Lstk(lw));
00318   if ( *istk(il) < 0 )
00319     il = iadr(*istk(il+1));
00320 
00321   if ( *istk(il) != SCI_SP_BOOLEAN )
00322     return 0;
00323 
00324   /* needed for Jpc stuff (putlhsvar) */
00325   Nbvars = Max(Nbvars,num);
00326   C2F(intersci).ntypes[num-1] = '$';
00327   C2F(intersci).iwhere[num-1] = *Lstk(lw);
00328   C2F(intersci).lad[num-1] = 0;  /* a voir ? */
00329 
00330   M->m  = *istk(il+1);
00331   M->n  = *istk(il+2);
00332   M->nel  = *istk(il+4);
00333   M->mnel = istk(il+5);
00334   M->jcol = istk(il+5+M->m);
00335   return 1;
00336 }
00337 
00338 
00339 #define ReshapeHMat(pos,H,new_dimsize) if (! reshape_hmat(pos,H,new_dimsize)) { return 0;}
00340 
00341 static int reshape_hmat(int pos, HyperMat *H, int new_dimsize)
00342 {
00343   /* 
00344    *   This utility routine is used when an hypermatrix H
00345    *   is indexed with fewer indices vectors than its dimsize
00346    *   (for instance the profil of H is n1 x n2 x n3 but
00347    *    an expression like H(v1,v2) is used). So we have to
00348    *    reconsidered the profil of H for this operation (in
00349    *    my example H is then considered with the profil
00350    *    n1 x (n2*n3) ). For that (as H is passed by reference)
00351    *    we create a new variable at position pos, recompute
00352    *    the new profil in this var and then H->dims will points to it.
00353    *
00354    */
00355   int *new_dims;
00356   int k, one=1, l;
00357 
00358   l = SCI_INT32; CreateVar(pos, "I", &new_dimsize, &one, &l);
00359   new_dims = istk(l);
00360   for ( k = 0 ; k < new_dimsize ; k++)
00361     new_dims[k] = H->dims[k];
00362   for ( k = new_dimsize ; k < H->dimsize ; k++ )
00363     new_dims[new_dimsize-1] *= H->dims[k];
00364   H->dimsize = new_dimsize;
00365   H->dims = new_dims;
00366   return 1;
00367 }
00368 
00369 static int cmpint(const void *pn1, const void *pn2)
00370 {
00371   int *n1 = (int *)pn1, *n2 = (int *)pn2;
00372   return (*n1 - *n2); 
00373 }
00374 
00375 static int index_convert(double *td, int * ti, int mn, int *ind_max)
00376 {
00377   /*  convert a scilab vector of indices (which are integers but
00378    *  stored as double) in an int vector together with 
00379    *  detecting the max index
00380    */
00381   int k, val;
00382   *ind_max = 0;
00383   for ( k = 0 ; k < mn ; k++ )
00384     {
00385       val = (int) td[k];
00386       if ( val <= 0 )
00387            return 0;
00388       if ( val > *ind_max )
00389         *ind_max = val;
00390       ti[k] = val - 1;
00391     }
00392   return 1;
00393 }
00394 
00395 static int create_index_vector(int pos, int pos_ind, int *mn, 
00396                                int nmax, int *ind_max)
00397 {
00398   /*  
00399    *   converti une "structure" scilab d'indicage en un vecteur d'indices
00400    *
00401    *      pos     : position de la variable initiale
00402    *      pos_ind : position de la variable resultante (le vecteur d'indice)
00403    *      mn      : taille du vecteur d'indice resultant
00404    *      ind_max : max de ce vecteur
00405    *      nmax    : utilise pour les descriptions implicites, aussi ind_max ne
00406    *                doit pas lui etre superieur
00407    */
00408       /* code based on SCI/routines/interf/indxg.f */
00409 
00410   int m, n, l, li, one=1, trois=3, *ti,/* val,*/ il, k, i, j, ideb, ipas, ifin, *P;
00411   double *td, px[3], x;
00412   HyperMat H;
00413   SciBoolSparse B;
00414   SciIntMat IV;
00415 
00416   switch ( GetType(pos) )
00417     {
00418     case (SCI_REAL_OR_CMPLX):
00419 
00420       GetRhsVar(pos, "d", &m, &n, &l);
00421       if ( m == -1 )      /* implicit index : */
00422         {
00423           *mn = nmax; *ind_max = nmax;
00424           li = 4; CreateVar(pos_ind, "I", mn,   &one,   &li); ti = istk(li); 
00425           for ( k = 0 ; k < *mn ; k++ )
00426             ti[k] = k;
00427           return 1;
00428         }
00429       else if ( m == 0 )  /* index is the void matrix [] */
00430         {
00431           *mn = 0; *ind_max = 0;
00432           return 1;
00433         }
00434       else                /* "normal" index */
00435         {
00436           td = stk(l); *mn = m*n; *ind_max = 0;
00437           li = 4; CreateVar(pos_ind, "I", mn,   &one,   &li); ti = istk(li); 
00438           return ( index_convert(td, ti, *mn, ind_max) );
00439         }
00440 
00441     case (SCI_INTEGER):
00442 
00443       GetRhsVar(pos, "I", &m, &n, (int *)&IV);
00444 
00445       if ( m <= 0 )      /* normaly not possible */
00446         return 0;
00447       else               /* "normal" index */
00448         {
00449           *mn = m*n; *ind_max = 0;
00450           li = 4; CreateVar(pos_ind, "I", mn,   &one,   &li); ti = istk(li);
00451           li = 4; C2F(tpconv)(&(IV.it), &li, mn, IV.D, &one, (void *) ti, &one); /* convert to usual int */
00452 
00453           for ( i = 0 ; i < *mn ; i++ )
00454             {
00455               if ( ti[i] <= 0 ) return 0;
00456               if ( ti[i] > *ind_max ) *ind_max = ti[i];
00457               ti[i]--;
00458             }
00459           return 1;
00460         }
00461 
00462     case (SCI_POLYNOMIAL):
00463 
00464       il = iadr( *Lstk( pos + Top - Rhs ) );
00465       if ( *istk(il) < 0 ) il = iadr( *istk(il+1) );
00466       m = *istk(il+1); n = *istk(il+2);
00467       if ( *istk(il+3) != 0 )
00468         return 0;
00469       *mn = m*n;
00470       l = sadr(il+9+*mn);
00471       CreateVar( pos_ind, "d", mn, &one, &li); td = stk(li);
00472       x = (double) nmax; 
00473       C2F(ddmpev)( stk(l), istk(il+8), &one, &x, td, &one, &one, mn);
00474       ti = (int *)td;
00475       return ( index_convert(td, ti, *mn, ind_max) );
00476 
00477     case (SCI_IMPLICIT_POLY):         /* p1:p2:p3 */
00478 
00479       il = iadr( *Lstk( pos + Top - Rhs ) );
00480       if ( *istk(il) < 0 ) il = iadr( *istk(il+1) );
00481       l = sadr( il+12 );
00482       x = (double) nmax; 
00483       C2F(ddmpev)( stk(l), istk(il+8), &one, &x, px, &one, &one, &trois);
00484       ideb = (int) px[0]; ipas = (int) px[1]; ifin = (int) px[2];
00485 
00486       if ( ipas == 0  ||  (ifin-ideb)*sign(ipas) < 0 )   /* index is finaly [] */
00487         {
00488           *mn = 0; *ind_max = -1;
00489           return 1;
00490         }
00491       else if ( (ipas < 0  &&  ifin <= 0)   ||  (ipas > 0  &&  ideb <= 0) )
00492         {
00493           return 0;    /* at least one index will be <= 0 => error */
00494         }
00495       else
00496         {
00497           *mn = (abs(ifin-ideb)+1)/abs(ipas);
00498           *ind_max = max(ideb, ifin);
00499           li = 4; CreateVar(pos_ind, "I", mn,   &one,   &li); ti = istk(li);
00500           ti[0] = ideb-1;  /* -1 to get 0-based indices */
00501           for ( k = 1 ; k < *mn ; k++ ) ti[k] = ti[k-1] + ipas;
00502           return 1;
00503         }
00504 
00505     case (SCI_BOOLEAN) :
00506 
00507       GetRhsVar(pos, "b", &m, &n, &l);
00508       if ( m*n != nmax )
00509         return 0;
00510       *mn = 0;
00511       for ( k = 0 ; k < nmax ; k++ )
00512         if ( *istk(l+k) != 0 )
00513           (*mn)++;
00514       if ( *mn == 0 )
00515         {
00516           *ind_max = 0; return 1;
00517         }
00518       li = 4; CreateVar(pos_ind, "I", mn,   &one,   &li); ti = istk(li); 
00519       i = 0;
00520       for ( k = 0 ; k < nmax ; k++ )
00521         if ( *istk(l+k) != 0 )
00522           {
00523             ti[i] = k; i++;
00524           }
00525       *ind_max = ti[*mn-1] + 1;
00526       return 1;
00527       
00528     case (SCI_MLIST) :         /* Try if it is an hypermat of BOOLEANS */
00529 
00530       GetHMat(pos, &H);
00531       if ( H.type != SCI_BOOLEAN ||  H.size != nmax)
00532         return 0;
00533       P = (int *) H.P;
00534       *ind_max = 0;
00535       *mn = 0;
00536       for ( k = 0 ; k < nmax ; k++ )
00537         if ( P[k] != 0 )
00538           (*mn)++;
00539       if ( *mn == 0 )
00540         {
00541           *ind_max = 0; return 1;
00542         }
00543       li = 4; CreateVar(pos_ind, "I", mn,   &one,   &li); ti = istk(li); 
00544       i = 0;
00545       for ( k = 0 ; k < nmax ; k++ )
00546         if ( P[k] != 0 )
00547           {
00548             ti[i] = k; i++;
00549           }
00550       *ind_max = ti[*mn-1] + 1;
00551       return 1;
00552       
00553 
00554     case (SCI_SP_BOOLEAN) :
00555 
00556       GetSciBoolSparse(pos, &B);
00557       if ( B.m*B.n != nmax )
00558         return 0;
00559 
00560       if ( B.nel == 0 )  /* false sparse matrix => index is [] */
00561         {
00562           *mn = 0; *ind_max = 0;
00563           return 1;
00564         }
00565 
00566       *mn = B.nel;
00567       li = 4; CreateVar(pos_ind, "I", mn,   &one,   &li); ti = istk(li); 
00568       if ( B.m == 1 )
00569         {
00570           for ( k = 0 ; k < B.nel ; k++ )
00571             ti[k] = B.jcol[k] - 1;
00572         }
00573       else if ( B.n == 1 )
00574         {
00575           i = 0;
00576           for ( k = 0 ; k < B.m ; k++ )
00577             if ( B.mnel[k] != 0 )
00578               {
00579                 ti[i] = k; i++;
00580               }
00581         }
00582       else
00583         {
00584           k = 0;
00585           for ( i = 0 ; i < B.m ; i++ )
00586             for ( l = 0 ; l < B.mnel[i] ; l++ )
00587               {
00588                 j = B.jcol[k] - 1; 
00589                 ti[k] = j*B.m + i;
00590                 k++;
00591               }
00592           qsort((void *)ti, (size_t) B.nel, sizeof(int), cmpint);
00593         }
00594       *ind_max = ti[*mn-1] + 1;
00595       return 1;
00596 
00597     default :
00598       return 0;
00599     }
00600 }
00601 
00602 
00603 static void compute_indices(int dec, int dimsize, int dims[], int j[])
00604 {
00605   /* 
00606    *   from an indexing (i0,i1,i2,...) of an hypermatrix of size
00607    *   dims[0] x dims[1] x dims[2] x....  computes the "real" one 
00608    *   dimensionnal indices (hypermatrices have the fortran order).
00609    */
00610 
00611   int nd, i, k, K, Knew, m, p, temp;
00612   int *id;
00613 
00614   get_length_and_pointer(dec+dimsize, &nd, &id);
00615   K = nd; 
00616   for ( k = 0 ; k < K ; k++ )
00617     j[k] = id[k];
00618 
00619   for ( i = dimsize-1 ; i > 0 ; i-- )
00620     {
00621       get_length_and_pointer(dec+i, &nd, &id);
00622       Knew = K * nd;
00623       m = Knew-1;
00624       for ( k = K-1 ; k >= 0 ; k--)
00625         {
00626           temp = dims[i-1] * j[k];
00627           for ( p = nd-1 ; p >= 0 ; p-- )
00628             {
00629               j[m] = id[p] + temp;
00630               m--;
00631             }
00632         }
00633       K = Knew;
00634     }
00635 }
00636 
00637 
00638 int C2F(intehm)()
00639 {
00640   /* 
00641    *  Extraction routine for an hypermatrix of type REAL_OR_COMPLEX, BOOLEAN
00642    *  and INTEGER (the 6 types of scilab ints) 
00643    *
00644    *    He = ehm ( v_1, v_2, ..., v_nb_iv, H ) 
00645    *
00646    */
00647   HyperMat H, He;
00648   int dec, i, k, l, m, n, mn, ntot, ind_max;
00649   int *j, ier, one=1, zero=0, ltot, nb_index_vectors, final_dimsize, lr, lc;
00650   int *P, *Pe;
00651   short int *siP, *siPe;
00652   char  *cP, *cPe;
00653 
00654 /*   CheckLhs(minlhs,maxlhs); */
00655 
00656   if ( Rhs < 2 ) 
00657     {
00658       Scierror(999," an hypermat extraction must have at least 2 args ");
00659       return(0);
00660     };
00661 
00662   if ( ! get_hmat(Rhs, &H) )
00663     {
00664       Scierror(999," argument is not an hypermatrix ");
00665       return 0;
00666     }
00667   else if ( H.type == NOT_REAL_or_CMPLX_or_BOOL_or_INT  || H.type == OLD_HYPERMAT )
00668     {
00669       /*  do the extraction with the macro %hm_e  */
00670       Fin = -Fin;
00671       return 0;
00672     }
00673 
00674   nb_index_vectors = Rhs-1;
00675   if ( H.dimsize <  nb_index_vectors )
00676     {
00677       Scierror(999," incompatible hypermat extraction ");
00678       return 0;
00679     }
00680   else if ( H.dimsize > nb_index_vectors )  /* reshape H */
00681     {
00682       ReshapeHMat(Rhs+1, &H, nb_index_vectors );
00683       dec = Rhs+1;
00684     }
00685   else
00686     dec = Rhs;
00687 
00688   if ( H.size == 0 )   /* the hypermat is empty => return an empty matrix ? */
00689     {
00690       CreateVar(dec+1, "d", &zero, &zero, &l);
00691       LhsVar(1) = dec+1;
00692       PutLhsVar();
00693       return 0;
00694     }
00695  
00696 
00697   ntot = 1;   /* will be the nb of elts of the extracted hmat or mat */
00698   for ( i = 1 ; i <= nb_index_vectors ; i++ )
00699     {  
00700       ier = create_index_vector(i, dec+i, &mn, H.dims[i-1], &ind_max);
00701       if ( ier == 0  ||  ind_max > H.dims[i-1] )
00702         {
00703           Scierror(999,"bad (%d th) index in hypermat extraction ",i); return 0;
00704         }
00705       if ( mn == 0 )   /* the vector index is [] => we return an empty matrix */
00706         {
00707           CreateVar(dec+i+1, "d", &zero, &zero, &l);
00708           LhsVar(1) = dec+i+1;
00709           PutLhsVar();
00710           return 0;
00711         }
00712       ntot *= mn; 
00713     }
00714 
00715   /*  For the Matlab compatibility : an hypermatrix of profil n1 x ... x nj x ... x nk 
00716    *  with  nj > 1 and nj+1 = ... = nk = 1 becomes an hypermatrix of profil n1 x ... x nj 
00717    *  Moreover, in scilab, if nj <= 2, we get in fact a matrix.
00718    */
00719   final_dimsize = nb_index_vectors;
00720   while (final_dimsize > 1 && get_length(dec + final_dimsize) == 1)
00721     final_dimsize--;
00722   if ( final_dimsize > 2 )   /* we create an hypermatrix for the extraction result */
00723     {
00724       He.dimsize = final_dimsize;
00725       He.size = ntot;
00726       He.it = H.it;
00727       He.type = H.type;
00728       CreateHMat(dec+Rhs, &He);
00729       for ( k = 0 ; k < final_dimsize ; k++ )
00730         He.dims[k] = get_length(dec+k+1);
00731     }
00732   else                /* we create a matrix  for the extraction result */
00733     {
00734       m = get_length(dec+1); 
00735       if (final_dimsize > 1)
00736         n = get_length(dec+2);
00737       else
00738         n = 1;
00739       switch (H.type)
00740         {
00741         case (SCI_REAL_OR_CMPLX):
00742           CreateCVar(dec+Rhs, "d", &(H.it), &m, &n, &lr, &lc); 
00743           He.R = stk(lr); 
00744           if ( H.it == 1 ) He.I = stk(lc);
00745           break;
00746         case (SCI_BOOLEAN):
00747           CreateVar(dec+Rhs, "b", &m, &n, &lr); 
00748           He.P = (void *) istk(lr);
00749           break;
00750         case (SCI_INTEGER):
00751           lr = H.it;
00752           CreateVar(dec+Rhs, "I", &m, &n, &lr);
00753           He.P = (void *) istk(lr);
00754           break;
00755         }
00756     }
00757 
00758   /* indices computing */
00759   ltot = 4; CreateVar(dec+Rhs+1, "I", &ntot, &one, &ltot); j = istk(ltot);
00760   compute_indices(dec, nb_index_vectors, H.dims, j);
00761 
00762   /*  fill the resulting hypermatrix or matrix  */
00763   switch ( H.type )
00764     {
00765     case (SCI_REAL_OR_CMPLX) :
00766       for ( k = 0 ; k < ntot ; k++ )
00767         He.R[k] = H.R[j[k]];
00768       if (H.it == 1)
00769         for ( k = 0 ; k < ntot ; k++ )
00770           He.I[k] = H.I[j[k]];
00771       break;
00772       
00773     case (SCI_BOOLEAN) :     /* (sci_boolean stored with 4 bytes) */
00774       Pe = (int *) He.P ; P = (int *) H.P;
00775       for ( k = 0 ; k < ntot ; k++ )
00776         Pe[k] = P[j[k]];
00777       break;
00778 
00779     case (SCI_INTEGER) :
00780       if ( H.it == SCI_INT32  ||  H.it == SCI_UINT32 )
00781         {
00782           Pe = (int *) He.P; P = (int *) H.P;
00783           for ( k = 0 ; k < ntot ; k++ )
00784             Pe[k] = P[j[k]];
00785         }
00786       else if ( H.it == SCI_INT16  ||  H.it == SCI_UINT16 )
00787         {
00788           siPe = (short int *) He.P; siP = (short int *) H.P;
00789           for ( k = 0 ; k < ntot ; k++ )
00790             siPe[k] = siP[j[k]];
00791         }
00792       else    /* SCI_INT8 and SCI_UINT8 : 1 Byte int */
00793         {
00794           cPe = (char *) He.P; cP = (char *) H.P;
00795           for ( k = 0 ; k < ntot ; k++ )
00796             cPe[k] = cP[j[k]];
00797         }
00798       break;
00799     }
00800   
00801   LhsVar(1) = dec+Rhs;
00802   PutLhsVar();
00803   return 0;
00804 }
00805 
00806 
00807 int C2F(intihm)()
00808 {
00809   /* 
00810       une routine d'insertion pour hypermatrice : cas le plus
00811       simple :   A( vi1, ..., vik ) = B
00812 
00813         ihm ( vi1, vi2, ..., vik, B, A ) 
00814 
00815       avec des vecteurs d'indices classiques vi1, vi2, ....
00816       et B une hypermatrice ou bien une matrice
00817    */
00818 
00819   HyperMat A, B;
00820   int i, k,/* l, li, m, n,*/ ntot, mn,/* err_neg,*/ iconf, ind_max;
00821   int nb_index_vectors, B_is_scalar;
00822   int *j,/* nd,*/ one=1, ltot, il, dec/*, Top_save*/;
00823   int *PA, *PB;
00824   short int *siPA, *siPB;
00825   char *cPA, *cPB;
00826   int ilp, topk;
00827 
00828 /*   CheckLhs(minlhs,maxlhs); */
00829 
00830   if ( Rhs < 3 ) 
00831     {
00832       Scierror(999," an hypermat insertion must have at least 3 args ");
00833       return 0;
00834     };
00835   nb_index_vectors = Rhs - 2;
00836 
00837   if ( ! get_hmat(Rhs, &A) )
00838     {
00839       Scierror(999," argument is not an hypermatrix ");
00840       return 0;
00841     }
00842   else if ( A.type == NOT_REAL_or_CMPLX_or_BOOL_or_INT  || A.type == OLD_HYPERMAT )
00843     {
00844       /* do the job by the %x_i_hm macro family */
00845       Fin = -Fin;
00846       return 0;
00847     }
00848 
00849   if ( ! get_hmat(Rhs-1, &B) )   /* B is not an hypermat => try if it is a matrix */
00850     if ( ! get_mat_as_hmat(Rhs-1, &B) )  /* it is not a matrix of type 1, 4 or 8 */
00851       {
00852         /* it stays some authorized possibilities like A(....) = B with B a polynomial
00853          * matrix and A a real hypermatrix => try the %x_i_hm macro family 
00854          */
00855         Fin = -Fin;
00856         return 0;
00857       }
00858 
00859 
00860   if ( A.type !=  B.type || A.it != B.it || B.size == 0  || A.dimsize <  nb_index_vectors ) 
00861     {
00862       /*  do the job by the %x_i_hm macro family */
00863       Fin = -Fin;
00864       return 0;
00865     }
00866 
00867   if ( B.size == 1 )
00868     B_is_scalar = 1;
00869   else
00870     B_is_scalar = 0;
00871 
00872 
00873   if ( A.dimsize > nb_index_vectors )
00874     {
00875       ReshapeHMat(Rhs+1, &A, nb_index_vectors);
00876       dec = Rhs+1;
00877     }
00878   else
00879     dec = Rhs;
00880 
00881 
00882   /* get the index vectors */
00883   ntot = 1;
00884   iconf = 0;
00885   for ( i = 1 ; i <= nb_index_vectors ; i++ )
00886     {  
00887       if (! create_index_vector(i, dec+i, &mn, A.dims[i-1], &ind_max)) return 0;
00888       if ( mn == 0 )   /* the i th index vector is [] */
00889         {
00890           if ( B_is_scalar )
00891             /* nothing append (strange but reproduces the Matlab behavior) */
00892             goto the_end;
00893           else   /* B have at least 2 elts */
00894             {
00895               Scierror(999," bad hypermat insertion "); return 0;
00896             }
00897         }
00898       else if ( ind_max > A.dims[i-1] )
00899         {
00900           /* we have to enlarge the hypermat : do the job by the %x_i_hm macro family */
00901           Fin = -Fin;
00902           return 0;
00903         }
00904       else if ( !B_is_scalar  &&  mn != 1 )  /* do the conformity test */
00905         {
00906           while ( iconf < B.dimsize  &&  B.dims[iconf] == 1 )
00907             iconf++;
00908           if ( iconf >= B.dimsize  ||  B.dims[iconf] != mn )
00909             {
00910               Scierror(999," bad hypermat insertion ");
00911               return 0;
00912             }
00913           iconf++;
00914         }
00915       ntot *= mn; 
00916     }
00917   /* to finish the conformity test */
00918   if ( !B_is_scalar &&  ntot != B.size )
00919     {
00920       Scierror(999," bad hypermat insertion ");
00921       return 0;
00922     }
00923 
00924   /* indices computing */
00925   ltot = 4; CreateVar(dec+Rhs-1, "I", &ntot, &one, &ltot); j = istk(ltot);
00926   compute_indices(dec, nb_index_vectors, A.dims, j);
00927 
00928   
00929   /*   modify in place the hypermatrix A  */
00930   switch ( A.type )
00931     {
00932     case (SCI_REAL_OR_CMPLX) :
00933       if ( B_is_scalar )
00934         {
00935           for ( k = 0 ; k < ntot ; k++ ) A.R[j[k]] = B.R[0];
00936           if (A.it == 1)
00937             for ( k = 0 ; k < ntot ; k++ ) A.I[j[k]] = B.I[0];
00938         }
00939       else
00940         {
00941           for ( k = 0 ; k < ntot ; k++ ) A.R[j[k]] = B.R[k];
00942           if (A.it == 1)
00943             for ( k = 0 ; k < ntot ; k++ ) A.I[j[k]] = B.I[k];
00944         }
00945       break;
00946       
00947     case (SCI_BOOLEAN) :
00948       PA = (int *) A.P ; PB = (int *) B.P;
00949       if ( B_is_scalar )
00950         for ( k = 0 ; k < ntot ; k++ ) PA[j[k]] = PB[0];
00951       else
00952         for ( k = 0 ; k < ntot ; k++ ) PA[j[k]] = PB[k];
00953       break;
00954 
00955     case (SCI_INTEGER) :
00956       if ( A.it == SCI_INT32  ||  A.it == SCI_UINT32 )
00957         {
00958           PA = (int *) A.P ; PB = (int *) B.P;
00959           if ( B_is_scalar )
00960             for ( k = 0 ; k < ntot ; k++ ) PA[j[k]] = PB[0];
00961           else
00962             for ( k = 0 ; k < ntot ; k++ ) PA[j[k]] = PB[k];
00963         }
00964       else if ( A.it == SCI_INT16  ||  A.it == SCI_UINT16 )
00965         {
00966           siPA = (short int *) A.P; siPB = (short int *) B.P;
00967           if ( B_is_scalar )
00968             for ( k = 0 ; k < ntot ; k++ ) siPA[j[k]] = siPB[0];
00969           else
00970             for ( k = 0 ; k < ntot ; k++ ) siPA[j[k]] = siPB[k];
00971         }
00972       else   /* 1 Byte int */
00973         {
00974           cPA = (char *) A.P; cPB = (char *) B.P;
00975           if ( B_is_scalar )
00976             for ( k = 0 ; k < ntot ; k++ ) cPA[j[k]] = cPB[0];
00977           else
00978             for ( k = 0 ; k < ntot ; k++ ) cPA[j[k]] = cPB[k];
00979         }
00980       break;
00981     }
00982 
00983 /*
00984  *  ici j'essaie de faire le boulot de putlhsvar
00985  *  le code se base sur  setref (SCI/system/createref.f)
00986  *  on met une variable speciale "en Top" (le nouveau
00987  *  Top = Top-Rhs+1) qui indique en fait que l'on a
00988  *  modifi� "en place" la variable topk.
00989  *  Les instructions  LhsVar(1) = 0; et Nbvars = 0;
00990  *  permettent a priori de sortir "convenablement"
00991  *  de putlhsvar.
00992  */
00993  the_end:
00994   il = iadr(*Lstk(Top));
00995   topk = *istk(il + 2);
00996   Top = Top - Rhs + 1;
00997   ilp = iadr(*Lstk(Top));
00998   *istk(ilp) = -1;
00999   *istk(ilp+1) = -1;
01000   *istk(ilp+2) = topk;
01001   if ( topk > 0 )
01002     *istk(ilp+3) = *Lstk(topk+1) - *Lstk(topk);
01003   else
01004     *istk(ilp+3) = 0;
01005   *Lstk(Top+1) = sadr(ilp+4);
01006 
01007   LhsVar(1) = 0;
01008   Nbvars = 0;
01009 
01010   return 0;
01011 }

Generated on Sun Mar 4 15:03:48 2007 for Scilab [trunk] by  doxygen 1.5.1