Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

robot/control/oldikor/IKOR/fsp.c

Go to the documentation of this file.
00001 /* ________________________________________________________
00002   |                                                        |
00003   | Program Name:   FSPv2.0.c                              |
00004   |________________________________________________________|
00005   |                                                        |
00006   | description:  Given the Jacobian and dx the procedure  |
00007   |     finds a a set of g vectors which span the solution |
00008   |     space of the equation to the equation J*q=dx, for  |
00009   |     all values of the vector q.                        |
00010   |                                                        |
00011   |                                                        |
00012   | Procedures:                                            |
00013   |     Solution_generator  :                              |
00014   |     RestofSoln          :                              |
00015   |     Dependency          :                              |
00016   |     BLOCK_COL_FIND_X    :                              |
00017   |     ReduceA             :                              |
00018   |     CheckB              :                              |
00019   |     CheckRange          :                              |
00020   |     Rebuild_gs          :                              |
00021   |________________________________________________________| */
00022 
00023 #include <IKOR/general.h>
00024 
00025 int  SystemComplete;    /* marks when all necessary vecs have been found*/
00026 int  DEBUG_FSP = TRUE;
00027 #define DEBUG 1
00028 /* ________________________________________________________
00029   | name:    Solution_generator                            |
00030   | description:  Main FSP procedure which sets up all     |
00031   |    initialization of variables, and starts production  |
00032   |    of g vectors.  After calling reduce it checks for   |
00033   |    SpecialCase2 then finds the first valid blocking    |
00034   |    pattern.  After which it calls RestofSoln and       |
00035   |    depending on the outcome it decides which method to |
00036   |    determine the solution vector.                      |
00037   |                                                        |
00038   |                                                        |
00039   | inputs:  Aorig, borig, M, N                            |
00040   | outputs: Ared, bred, Mred, Nred, Xelim, ColElim,       |
00041   |          RowElim, g                                    |
00042   |________________________________________________________|
00043   | Authors:     Date:     Modifications:                  |
00044   |  g fries     3/95      Created                         |
00045   |________________________________________________________| */
00046 
00047 extern FILE* gcheck;     
00048 
00049 int Solution_generator(FSP_data, Aorig, borig, check)
00050 FILE      *check;
00051 MATRIX    *Aorig,
00052           *borig;
00053 Solutions *FSP_data;
00054 {
00055 MATRIX  *Ared,          /* reduced A                                    */
00056         *Asub,          /* submatrix from square submatrix is found     */
00057         *Asqr,          /* square submatrix                             */
00058         *bred,          /* reduced b                                    */
00059         *block,         /* locations of blocked columns for each soln   */
00060         *n,             /* null space vectors                           */
00061         *Specialg;      /* null vectors created by SpecialCase1         */
00062 float   K2,             /* matrix condition number:  sv_max/sv_min      */
00063         N_BND;          /* min acceptable value for nonzero nspace comp */
00064 int     i, j, k, I,     /* loop counters                                */
00065         bcheck,         /* check for completely zero bred               */
00066        *ColElim,        /* marks columns eliminated from original A     */
00067        *RowElim,        /* which rows are to be eliminated from the A   */
00068         move,           /* which of four possible blocks is being moved */
00069         NextToFind,     /* vector number being searched for             */
00070        *Tackon,         /* columns are indexed for effic, soln finding  */
00071        *FirstOK,        /* if OK to substitute in for firstsoln column  */
00072         pos,            /* used with the Ordering[] variable            */
00073         nullity,        /* dimension of null space                      */
00074         binrange,       /* marks if b is in the range of the A          */
00075         Exit_Status,    /* tells calling routine if OK                  */
00076         NumSpg,         /* number of g vectors created by SpecialCase1  */
00077         Stop;           /* loop flag to end                             */
00078 
00079   /* allocate memory space for variables */
00080   Tackon  = ( int *) malloc ( (M - N) * sizeof( int ) );
00081   FirstOK = ( int *) malloc (    N    * sizeof( int ) );
00082   ColElim = ( int *) malloc (    M    * sizeof( int ) );
00083   RowElim = ( int *) malloc (    N    * sizeof( int ) );
00084   Ared    = mat_malloc(N, M);
00085   bred    = mat_malloc(N, 1);
00086   Specialg= mat_malloc((M-1),M);
00087 
00088   gcheck=check;
00089   /* initialize SystemComplete and FirstOK */
00090   SystemComplete = FALSE;
00091   for (i=0; i< N; i++)
00092     FirstOK[i] = FALSE;
00093 
00094   if ( (bcheck = (CheckB(borig, FSP_data->N))) == ZERO )
00095   {
00096     for (i=0; i< FSP_data->N; i++) 
00097       borig->p[i][0] = (i<3) ? 1.0:0.0;
00098     FSP_data->Null_Space = TRUE;  
00099   }
00100   else
00101     FSP_data->Null_Space = FALSE;
00102 
00103   /*check = stderr;             /* uncomment when in trouble    */
00104   /* Eliminate all the nonredundancies from the A and b */
00105   ReduceA(FSP_data, Aorig, Ared, borig, bred,ColElim,RowElim,
00106                                                         &NumSpg, Specialg);
00107   /* Setup and initialization of g vectors */
00108   mat_free(FSP_data->g);
00109   FSP_data->g = mat_malloc((FSP_data->Mred-FSP_data->Nred+1+NumSpg), M);
00110   for (i=0; i<(SPAN); i++)
00111     for (j=0; j<M; j++) FSP_data->g->p[i][j] = 0.0e0;
00112 
00113 
00114 if (DEBUG) {
00115   fprintf(check,"\n  ______________________________  \n");
00116   fprintf(check,"\n                FSP               \n");
00117   fprintf(check,  "  ______________________________  \n\n");
00118   fmat_pr(check, " Jacobian ", Aorig);
00119   fmat_pr(check, " requested dx ", borig); 
00120   fprintf(check, " M   : %d, N   : %d\n Mred: %d, Nred: %d",
00121                    M, N, FSP_data->Mred, FSP_data->Nred);
00122   fprintf (check, "\nRowElim: ");
00123   for (i=0; i< N; i++) fprintf (check,"%d ", RowElim[i]);
00124   fprintf (check, "\nColElim: ");
00125   for (i=0; i< M; i++) fprintf (check,"%d ", ColElim[i]);
00126   fmat_pr(check, " *** Xelim *** ", FSP_data->Xelim);
00127   if(FSP_data->Null_Space) fprintf(check,"\nGenerating NullSpace Solutions.\n");
00128 }
00129 if (DEBUG_FSP) {
00130   fmat_pr(check, " *** A Reduced *** ", Ared);
00131   fmat_pr(check, " *** b Reduced *** ", bred);
00132 
00133 }             /* if DEBUGGING, include code  (see file info) */
00134 
00135 bcheck=CheckB(bred, FSP_data->Nred);
00136 if (bcheck == 0)
00137     {
00138     n = mat_malloc(FSP_data->Mred, FSP_data->Nred);
00139     if (DEBUG_FSP) fprintf(check, "GIVEN MATRIX IS COMPLETELY RESTRICTED\n\n");
00140     Asub = mat_malloc(FSP_data->Nred, FSP_data->Mred);
00141     for (i=0; i < FSP_data->Nred; i++)
00142         for (j=0; j < FSP_data->Mred; j++)
00143             Asub->p[i][j] = Ared->p[i][j];
00144     mat_null(Asub, &nullity, n, &K2);
00145 
00146     /* set the solution vectors for a completely restricted system  */
00147     for (i=0; i < FSP_data->Mred; i++)
00148         for (j=0; j< SPAN2 - 1; j++)
00149             FSP_data->g->p[j][i] = n->p[i][j];
00150     for (i=0; i < FSP_data->Mred; i++)
00151         FSP_data->g->p[FSP_data->Mred-FSP_data->Nred][i] = 0.0;
00152     SystemComplete = TRUE;
00153 
00154     Exit_Status = RESTRICTED;
00155     if (DEBUG_FSP) fmat_pr(check, "solutions", FSP_data->g);
00156 
00157     mat_free(Asub);
00158     mat_free(n);
00159     }
00160 else
00161     {
00162     n = mat_malloc(FSP_data->Nred, FSP_data->Nred);
00163     if (FSP_data->Nred != N)
00164         {
00165             if (DEBUG_FSP) {
00166               fprintf(check, "GIVEN MATRIX IS RESTRICTED FOR %d ",
00167                  N-FSP_data->Nred);
00168               fprintf(check, "OUT OF %d VECTOR COMPONENTS\n\n", N);
00169             }
00170         }
00171 
00172     block= mat_malloc(SPAN2,FSP_data->Nred);
00173     Asqr = mat_malloc(FSP_data->Nred,FSP_data->Nred);
00174     NextToFind = 0;
00175 
00176     /* initialize the blocking positions for the first solution vector */
00177     if (DEBUG_FSP) 
00178         for (i=0; i<(FSP_data->Nred); i++) 
00179              for (j=0; j<(FSP_data->Mred-FSP_data->Nred+1); j++)
00180                 block->p[j][i] = 0;
00181 
00182     for (i=0; i<(FSP_data->Nred); i++)
00183         block->p[0][i] = i;
00184     k=0;
00185     for (i=0; i<FSP_data->Mred; i++)
00186       if (block->p[0][k] == i)
00187          {
00188          for (j=0; j<FSP_data->Nred; j++)
00189             Asqr->p[j][k] = Ared->p[j][i];
00190          k++;
00191          }
00192     mat_null(Asqr, &nullity, n, &K2);
00193 
00194     if (DEBUG_FSP) {
00195         fmat_pr (check, "block", block);
00196         fmat_pr (check, "Asqr", Asqr);
00197         fmat_pr (check, "n", n);
00198         fprintf(check,"nullity = %d, K2 = %f\n", nullity, K2);
00199     }     /* if DEBUGGING, include code  (see file info) */
00200 
00201     /* loop until an acceptable well-conditioned first solution found */
00202     while ((nullity != 0) && (block->p[0][0]<N))
00203         {
00204 fprintf(check,"while:\n");
00205         pos = FSP_data->Nred-1;
00206         while (block->p[0][pos] == SPAN2 - 1 +pos)
00207             pos--;
00208         block->p[0][pos]++;
00209         move=pos+1;
00210         while (move<FSP_data->Nred)
00211             {
00212             block->p[0][move]=block->p[0][(move-1)]+1;
00213             move++;
00214             }
00215         k=0;
00216         for (i=0; i<FSP_data->Mred; i++)
00217             if (block->p[0][k] == i)
00218                 {
00219                 for (j=0; j<FSP_data->Nred; j++)
00220                     Asqr->p[j][k] = Ared->p[j][i];
00221                 k++;
00222                 }
00223         if (block->p[0][0] <= FSP_data->Nred)
00224             mat_null(Asqr, &nullity, n, &K2);
00225         if (DEBUG_FSP) {
00226             fmat_pr(check, "block", block);
00227             fmat_pr(check, "Asqr", Asqr);
00228             fprintf(check, "nullity = %d, K2 = %f\n", nullity, K2);
00229           }
00230         }
00231 
00232     k=0; I=0;
00233     for (i=0; i<FSP_data->Mred; i++)
00234         if ((k < FSP_data->Nred) && (block->p[0][k] == i))
00235            k++;
00236         else
00237             {
00238             Tackon[I]=i;
00239             I++;
00240             }
00241 fprintf(check,"calling BLOCK_COL_FIND_X\n");
00242     BLOCK_COL_FIND_X(Tackon,FSP_data->g->p[NextToFind],block->p[NextToFind],
00243                 bred,Ared,FSP_data->Mred,FSP_data->Nred,check);
00244 
00245     if (DEBUG_FSP) {
00246         fprintf(check, "first solution \n");
00247         fmat_pr(check, "block", block);
00248         fmat_pr(check, "Asqr", Asqr);
00249         for (i=0; i<FSP_data->Mred-FSP_data->Nred;i++)
00250           fprintf(check, "here %d", Tackon[i]);
00251     }
00252     fprintf(check,"Nred=%d Mred=%d\n",FSP_data->Nred, FSP_data->Mred);
00253     if (FSP_data->Nred==FSP_data->Mred)
00254         SystemComplete=TRUE;
00255     else
00256         RestofSoln(FSP_data->Mred, FSP_data->Nred, NextToFind, block,
00257                    FSP_data->g, bred, Ared, Tackon, FirstOK, check);
00258 
00259     if (DEBUG_FSP) {
00260       fmat_pr(check, "block", block);
00261       fmat_pr(check, "solutions", FSP_data->g);
00262       }
00263    mat_free(block);
00264    mat_free(Asqr);
00265    mat_free(n);
00266    }
00267 
00268 
00269 
00270         /* check if the eliminated b elements in bred can be    */
00271         /* produced from the g vectors and the reduced A matrix */
00272         /* ie check that b is in the range of A                 */
00273    if (!SystemComplete)
00274    {
00275         IKerror(25,OK,"");
00276         binrange = 0;
00277    }
00278    else
00279       binrange = CheckRange(borig, Aorig, FSP_data->g, RowElim,
00280                             FSP_data->Mred);
00281 
00282         /* check that the original b was not all zeros (special case) */
00283    bcheck = CheckB(borig, M);
00284 
00285         /* check whether the original A had dependent rows  */
00286    if ((binrange) && (bcheck != 0) && (Exit_Status != RESTRICTED))
00287    {
00288      Rebuild_gs (FSP_data, ColElim, Specialg, NumSpg);
00289      Exit_Status = COMPLETE;
00290      for (i=0; (( i < N ) && (FSP_data->cn == 0)); i++)
00291      {
00292        if (RowElim[i] != 2)
00293          i++;
00294        else {
00295          /* Code should be inserted here or in ReduceA to determine     */
00296          /* whether or not the b's are dependent as well, if they are   */
00297          /* nothing needs to happen, if they aren't... an error mess-   */
00298          /* should be generated and the system should halt.             */
00299          /* Currently this will occur since the A matrix in the findt's */
00300          /* will be the zero matrix and cause a zero division error.    */      
00301        }
00302      }
00303    }
00304    else if (Exit_Status != RESTRICTED)
00305    {
00306      Exit_Status = NOT_COMPLETE;
00307      if (bcheck != 0)
00308        fprintf(check, "\n\nB NOT IN RANGE OF A\n");
00309      else
00310        fprintf(check, "\n\n%s\n%s", "SPECIAL CASE\nB IS ZERO VECTOR",
00311          "CONSTRAINED OPTIMIZATION MUST BE USED\n");
00312    }
00313 
00314 /* free up all variable memory space */
00315 mat_free(Ared);
00316 mat_free(bred);
00317 mat_free(Specialg);
00318 free(Tackon);
00319 free(FirstOK);
00320 free(ColElim);
00321 free(RowElim);
00322 
00323 return (Exit_Status);
00324 }
00325 
00326 
00327 
00328 /* ________________________________________________________
00329   | name:    RestofSoln                                    |
00330   | description:  Finds the remaining solution vectors     |
00331   |               after the first has been selected.  It is|
00332   |               recursive and thus calls itself when a   |
00333   |               valid solution is found, if this solution|
00334   |               leads to a dead end, it will pop back to |
00335   |               last solution and build from there.  This|
00336   |               insures that all possible combinations of|
00337   |               blocking patterns are available, given   |
00338   |               first one, in pattern which follows the  |
00339   |               algoritm presented in the article.       |
00340   |                                                        |
00341   |                                                        |
00342   | inputs:  Mred, Nred, NextToFind, block, g, bred, Ared, |
00343   |          Tackon, FirstOK                               |
00344   | outputs: block, g                                      |
00345   |________________________________________________________|
00346   | Authors:     Date:     Modifications:                  |
00347   |  g fries     2/95      Created                         |
00348   |  g fries     3/95      Addition of SpecialCase2 case   |
00349   |________________________________________________________| */
00350 
00351 void RestofSoln (int Mred, int Nred, int NextToFind, MATRIX *block,
00352                  MATRIX *g, MATRIX *bred, MATRIX *Ared, int *Tackon,
00353                  int *FirstOK, FILE *check)
00354 {
00355 int     i, j, k, /*Loop counters                                      */
00356         X, Y,    /*Position markers, keeping track of the current     */
00357                  /*column to be subbed in for and which one to sub in */
00358         nullity, /*Nullity sent to mat_null for dependent rows        */
00359         Newtack[M-N], /*Temp array for tackon, sent to the next level of   */
00360                  /*recursion                                          */
00361        *Changed; /*Temp array for FirstOK, sent to the next level of  */
00362                  /*recursion                                          */
00363 MATRIX  *n,      /*null space vectors                                 */
00364         *Asub;   /*submatrix from square submatrix is found           */
00365 float K2;
00366 
00367 Changed = (int *) malloc (  Nred * (sizeof( int )) );
00368  fprintf(check, "entering RestOfSoln\n");
00369 /*Increment NextToFind so looking for next solution */
00370 NextToFind++;
00371 X = NextToFind -1;
00372 
00373 /*Change FirstOK if a previously 0 value of g for a column in first  */
00374 /*blocking pattern has become nonzero                                */
00375 for (i=0; i<Nred; i++)
00376   if ((!FirstOK[i]) && 
00377   (fabs(g->p[NextToFind-1][(int) block->p[NextToFind-1][i]]) > SMALL))
00378   {
00379      FirstOK[i] = TRUE;
00380   }
00381 
00382 for (j=0; j<Nred; j++)
00383 {
00384   if (DEBUG_FSP) {
00385      if (j==0) fprintf(check,"\nFIRST OK:  ");
00386      fprintf(check," %d ", FirstOK[j]);
00387      if (j==Nred-1) fprintf(check,"\n\n");
00388   }
00389   Changed[j] = FirstOK[j];
00390 }
00391 
00392 while ((X<(Mred-Nred))&&(!SystemComplete))
00393     {
00394     if (DEBUG_FSP) 
00395       fprintf(check,"\n Next Solution to find is: %d \n", NextToFind);
00396     
00397 
00398     /*Set up next asub comparing the next remaining column to be subbed */
00399     /*in with the blocking pattern for that level of recursion          */
00400     Asub = mat_malloc(Nred,Nred+1);
00401     for (i=0; i<Nred; i++)
00402         for (j=0; j<Nred; j++)
00403             Asub->p[j][i] = Ared->p[j][(int)block->p[(NextToFind-1)][i]];
00404     for (j=0; j<Nred; j++)
00405       Asub->p[j][Nred] = Ared->p[j][Tackon[X]];
00406     if (DEBUG_FSP) fmat_pr(check, "Asub", Asub);
00407 
00408     n = mat_malloc(Nred+1,1);
00409     mat_null(Asub, &nullity, n, &K2);
00410     mat_free(Asub);
00411     if (DEBUG_FSP) fmat_pr(check, "n", n);
00412     Y=0;
00413 
00414     /*Loop which compares column to be subbed in with current blocking */
00415     /*pattern for dependency, if dependent it completes swap and valid */
00416     while ((Y<(Nred))&&(!SystemComplete))
00417         {
00418         if (DEBUG_FSP) {
00419           fprintf(check,"\n Compare column %d with %d \n", Tackon[X], 
00420                                         (int)block->p[(NextToFind-1)][Y]);
00421           fprintf(check, "\n it is %f \n",fabs(n->p[Y][0]));
00422         }
00423         if ((fabs(n->p[Y][0]) > SMALL) && (FirstOK[Y]))
00424             {
00425             if (DEBUG_FSP) 
00426               fprintf(check, "*************** %d **************** \n", 
00427                                                                 NextToFind);
00428             fmat_pr(check,"\n** block",block);
00429             fprintf(check,"** Tackon=");
00430             for(j=0; j<(M-N); j++)
00431               fprintf(check,"%d ",Tackon[j]);
00432             fprintf(check,"\nX=%d Y=%d\n",X,Y);
00433 
00434             for (i=0; i<Nred;i++)
00435                 block->p[NextToFind][i]=block->p[(NextToFind-1)][i];
00436             Newtack[0]=(int)block->p[NextToFind][Y];
00437             block->p[NextToFind][Y] =Tackon[X];
00438             for (i=0; i<X; i++)
00439                 Newtack[i+1]=Tackon[i];
00440             for (j=X+1; j<(Mred-Nred); j++) {
00441                 Newtack[j]=Tackon[j];   
00442             }
00443 
00444             fprintf(check,"** Newtack=");
00445             for(j=0; j<(Mred-Nred); j++)
00446               fprintf(check,"%d ",Newtack[j]);
00447             fmat_pr(check,"\n** block",block);
00448             fmat_pr(check,"** g",g);
00449 
00450             BLOCK_COL_FIND_X(Newtack,g->p[NextToFind], block->p[NextToFind], 
00451                                                 bred,Ared,Mred,Nred,check);
00452 
00453             fmat_pr(check,"** block",block);
00454             fmat_pr(check,"** g",g);
00455 
00456             if (DEBUG_FSP) 
00457               fprintf(check, "\n it will be %f \n",fabs(g->p[(NextToFind)] 
00458                                 [(int)block->p[NextToFind][Y]]));
00459 
00460             /*Check to ensure the newly created g vector is independent */
00461             /*of previously created ones in branch                      */
00462             if (fabs(g->p[(NextToFind)][(int)block->p[NextToFind][Y]]) >SMALL)
00463                 if (NextToFind <(Mred-Nred))
00464                     {
00465                     if (DEBUG_FSP) {
00466                         fmat_pr(check, "block", block);
00467                         fmat_pr(check, "solutions", g);
00468                         for (i=0; i<(Mred-Nred); i++)
00469                             fprintf(check, "Ord %d",Newtack[i]);
00470                     }
00471                     /*if more g vectors are needed it goes to next level*/
00472                     RestofSoln(Mred, Nred, NextToFind, block, g, bred, Ared, 
00473                                Newtack, Changed, check);
00474                     }
00475                 else
00476                     {
00477                     SystemComplete = TRUE;
00478                     }
00479             if (!SystemComplete)
00480                 block->p[NextToFind][Y]=Newtack[0];
00481             if (DEBUG_FSP) fprintf(check, "\n **************************** \n");
00482             }
00483         Y++;
00484         }
00485    mat_free(n);
00486     X++;
00487     }
00488 
00489   free (Changed);
00490 }
00491 
00492 
00493 
00494 /* ________________________________________________________
00495   | name:    Dependency                                    |
00496   | description:  Returns whether or not the given two     |
00497   |               columns are dependent upon each other or |
00498   |               not.  Essential for detection of an      |
00499   |               occurance of SpecialCase1.               |
00500   |                                                        |
00501   |                                                        |
00502   | inputs:  Aorig, SLRow, Nred, first, second             |
00503   | outputs: whether columns SLRow[first] and SLRow[second]|
00504   |          are dependent                                 |
00505   |________________________________________________________|
00506   | Authors:     Date:     Modifications:                  |
00507   |  g fries     3/95      Created                         |
00508   |________________________________________________________| */
00509 
00510 int Dependency (MATRIX *Atemp, int *SLRow, int Nred, int first, int second)
00511 {
00512 int i,STOP;
00513 float devidor;
00514 i=0;
00515 devidor=0;
00516 STOP=FALSE;
00517 while (i<Nred && !STOP)
00518     if ((fabs(Atemp->p[SLRow[i]][first])<SMALL) && 
00519                                 (fabs(Atemp->p[SLRow[i]][second])<SMALL))
00520         i++;
00521     else if ((fabs(Atemp->p[SLRow[i]][first])>SMALL) &&
00522                                 (fabs(Atemp->p[SLRow[i]][second])>SMALL))
00523         if (devidor==0)
00524             {
00525             devidor= (Atemp->p[SLRow[i]][first]/Atemp->p[SLRow[i]][second]);
00526             i++;
00527             }
00528         else if (fabs(Atemp->p[SLRow[i]][first]-
00529                         (Atemp->p[SLRow[i]][second]*devidor))<SMALL)
00530             i++;
00531         else
00532             STOP=TRUE;
00533     else
00534         STOP=TRUE;
00535 if (STOP)
00536     return(FALSE);
00537 else
00538     return(TRUE);
00539 }
00540 
00541 
00542 
00543 
00544 /* ________________________________________________________
00545   | name:    BLOCK_COL_FIND_X                              |
00546   | description:  This procedure calculates a g vector for |
00547   |               a given square blocking pattern.         |
00548   |                                                        |
00549   |                                                        |
00550   | inputs:  Tackon, g, block, bred, Ared, Mred, Nred      |
00551   | outputs: new g vector                                  |
00552   |________________________________________________________|
00553   | Authors:     Date:     Modifications:                  |
00554   |  k morganson 8/94      Created                         |
00555   |  g fries     2/95      Adaption for new blocking       |
00556   |                        strategy (keeping blocked col)  |
00557   |________________________________________________________| */
00558 
00559 BLOCK_COL_FIND_X        (int *Tackon, float *g, float *block,
00560                          MATRIX *b, MATRIX *A, 
00561                          int Mred, int Nred, FILE *check)
00562 {
00563 int r, I, i, j,k;
00564 float  *blocktemp, temp;
00565 MATRIX *Atemp, *gtemp, *btemp;
00566 
00567 Atemp = mat_malloc(Nred,Nred);
00568 btemp = mat_malloc(Nred,1);
00569 blocktemp = (float *) malloc( Nred * sizeof(float) );
00570 
00571 for (i=0; i<Nred; i++)
00572    btemp->p[i][0]=b->p[i][0];
00573 /* the columns blocked need to be listed from smallest to largest */
00574 for (i=0; i<(Nred); i++)
00575    blocktemp[i]=(int)block[i];  
00576 
00577 
00578 for (i=(Nred-1); i>0; i--)
00579    for (j=i-1; j>=0; j--)
00580       if (blocktemp[i]<blocktemp[j])
00581          {
00582          temp=blocktemp[i];
00583          blocktemp[i]=blocktemp[j];
00584          blocktemp[j]=temp;
00585          }
00586 
00587 
00588 fprintf(gcheck,"Mred=%d Nred=%d\n",Mred,Nred);
00589    k=0; I=0;
00590    for (i=0; i<Mred; i++) {
00591       if (blocktemp[k] == i)
00592          {
00593          for (j=0; j<Nred; j++)
00594             Atemp->p[j][k] = A->p[j][i];
00595          k++;
00596          }
00597       else
00598         I++;
00599    }
00600 if (DEBUG_FSP) fmat_pr(check, "asqr", Atemp);
00601 
00602 
00603 mat_LU_inv(Atemp);
00604 
00605 gtemp = mat_mul2(Atemp, btemp);
00606 
00607 if (DEBUG_FSP) {
00608   fprintf(check, "\n gvector");
00609   for (i=0; i<Nred; i++)
00610     fprintf(check, "%f    ", gtemp->p[i][0]);
00611 }
00612 
00613 /*Now add a zero to where column was blocked */
00614 j=0;
00615 I=0;
00616 for (i=0; i<Nred; i++)
00617    g[(int)blocktemp[i]]=gtemp->p[i][0];
00618 
00619 for (j=0; j<(Mred-Nred); j++)  
00620       g[Tackon[j]]=0.0e0;
00621 
00622  fprintf(check,"\n** BLOCK_COL_FIND_X grow="); 
00623  for (j=0; j< N; j++)
00624    fprintf(check, "%f    ",g[j]);
00625 
00626 mat_free(Atemp);
00627 mat_free(gtemp);
00628 mat_free(btemp);
00629 free (blocktemp);
00630 }
00631 
00632 
00633 
00634 /* ________________________________________________________
00635   | name:    ReduceA                                       |
00636   | description:  Restricted work space motions can be     |
00637   |               identified by rows of the A which only   |
00638   |               have one nonzero element.  Since the     |
00639   |               corresponding column must be present in  |
00640   |               all final joint space solutions, the     |
00641   |               appropriate joint space motion will be   |
00642   |               calculated before any redundancy         |
00643   |               resolution is performed, and the         |
00644   |               appropriate motions and joints will be   |
00645   |               removed from the work space and A        |
00646   |               respectively.  Also such cases as        |
00647   |               dependent rows, and SpecialCase1 must be |
00648   |               identified and dealt with.               |
00649   |                                                        |
00650   |                                                        |
00651   | inputs:  Tackon, g, block, bred, Ared, Mred, Nred      |
00652   | outputs: new g vector                                  |
00653   |________________________________________________________|
00654   | Authors:     Date:     Modifications:                  |
00655   |  k morganson 8/94      Created                         |
00656   |  g fries     2/95      Adaption for new blocking       |
00657   |                        strategy and handling of dep row|
00658   |  g fries     3/95      Recognition and handling of     |
00659   |                        SpecialCase1 and cont reduction |
00660   |  c hacker    9/95      the new b was wrong, corrected  |
00661   |  c hacer    10/95      dependent rows bug fixed        |
00662   |________________________________________________________| */
00663 
00664 ReduceA(Solutions *FSP_data, MATRIX *Aorig, MATRIX *Ared, MATRIX *borig,
00665         MATRIX *bred, int* ColElim,int* RowElim,
00666         int *NumSpg, MATRIX *Specialg)
00667 
00668 {
00669 int i,j,k,m,r,p,   /*loop counters                                      */
00670     StillChecking, /*flag to mark when all nonredundancies are gone     */
00671     Stop,Stop2,    /*Used as loop flag in detection for SpecialCase1&2  */
00672     ClassANum,     /*Number of ClassificationA columns, for SpecialCase2*/
00673     reference,     /*Reference position used for SpecialCase2 row       */
00674     LastNred,      /*Check if all rows have been looked at              */
00675     nullity,       /*Used in mat_null when determining depend rows      */
00676     nul_count,     /*Loop counter for dependent rows                    */ 
00677     Restriction,   /*num of joints which contrib to a work space d.o.f. */
00678     DoneRed,       /*Keeps track if reduction is done, loop has executed*/
00679                    /*without any reduction                              */
00680     *SLRow,        /*Stands for Still Left Row, stores remaining non    */
00681                    /*eliminated rows in sequence                        */
00682     *SLCol,        /*Stands for Still Left Column, stores remaining non */
00683                    /*eliminated columns in sequence                     */
00684     *ClassA,       /*Array used to store ClassificationA columns        */
00685     count,count2,  /*Position markers when copying over SLCol when the  */
00686     position,      /*  SpecialCase1 has been found                      */
00687     nonzerocol,    /*Number of nonzero col when check for SpecialCase1  */
00688     *Nonzero,      /*Stores values of nonzero col when check for SC1    */
00689     NonZeroCol,    /*Column which has nonzero element for give row      */
00690     Flag,          /*Used in SC2 for an undefined beta value            */
00691     Goin;          /*"Go in" for entance into ClassA for SC2            */
00692 float btemp[N],    /*Holds the b vector as it is modified by backsub    */
00693       K2,          /*Matrix condition number:  sv_max/sv_min            */
00694       *Constant,   /*Constant values used when comparing ClassificationA*/
00695                    /*columns                                            */
00696       beta;        /*Value used for determining SpecialCase2            */
00697 MATRIX  *n,        /*null space vectors                                 */
00698         *Atrans,   /*Transpose matrix used when looking for depend rows */
00699         *AElim;    /*Matrix used to find null vectors when dealing with */
00700                    /* SpecialCase1                                      */
00701 
00702      /* allocation of memory */
00703 SLRow   = (int   *) malloc ( (N) * (sizeof( int )) );
00704 SLCol   = (int   *) malloc ( (M) * (sizeof( int )) );
00705 Nonzero = (int   *) malloc ( (M) * (sizeof( int )) );
00706 ClassA  = (int   *) malloc ( (M) * (sizeof( int )) );
00707 Constant= (float *) malloc ( (N) * (sizeof( float )) );
00708 
00709 printf("here0 N=%d M=%d\n",N,M);
00710 
00711      /* initialize variables */
00712 FSP_data->Nred = N;    /* number of rows in the reduced A       */
00713 FSP_data->Mred = M;    /* number of columns in the reduced A    */
00714 *NumSpg=0;
00715 for (i=0; i<N; i++)
00716    {
00717    SLRow[i]=i;
00718    RowElim[i]=0;
00719    btemp[i]=borig->p[i][0];
00720    }
00721 for (i=0; i<M; i++)
00722    {
00723    SLCol[i]=i;
00724    FSP_data->Xelim->p[i][0]=0.0;
00725    ColElim[i]=0;
00726    }
00727 DoneRed=FALSE;
00728 
00729 
00730      /* start reduction  */
00731 while (!DoneRed)
00732     {
00733     DoneRed=TRUE;
00734     StillChecking = 1; 
00735      /* Check each row for the number of nonzero elements.  If only one */
00736      /* element is nonzero, solve for the joint space motion, and       */
00737      /* modify the b vector so that the appropriate row and column      */
00738      /* can be eliminated from the A.  After a row is eliminated        */
00739      /* the remaining A must be rechecked for any new restrictions      */
00740     while (StillChecking)
00741         {
00742         LastNred = FSP_data->Nred;
00743         for (i=0; i<FSP_data->Nred; i++)
00744             {
00745             j=-1;
00746             Restriction=0;
00747 
00748             /* check for nonzero row elements */
00749             while ((j<(FSP_data->Mred-1)) && (Restriction < 2)) 
00750                 {
00751                 j++;
00752                 if (fabs(Aorig->p[SLRow[i]][SLCol[j]]) > SMALL)
00753                     {
00754                     Restriction++;
00755                     NonZeroCol = j;
00756                     }
00757                 }
00758 
00759             /* if a row only has one nonzero element, eliminate it from */
00760             /* the A                                             */
00761             if ((Restriction == 1) && (RowElim[SLRow[i]] != 1))
00762                 {
00763 /* HERE CJH */  FSP_data->Xelim->p[SLCol[NonZeroCol]][0]=(FSP_data->Null_Space)?
00764                       0.0:btemp[SLRow[i]]/Aorig->p[SLRow[i]][SLCol[NonZeroCol]];
00765                 for (k=0; k<FSP_data->Nred; k++)
00766                     btemp[SLRow[k]]= btemp[SLRow[k]]-Aorig->p[SLRow[k]][SLCol
00767                         [NonZeroCol]]*FSP_data->Xelim->p[SLCol[NonZeroCol]][0];
00768                 ColElim[SLCol[NonZeroCol]]=1;
00769                 RowElim[SLRow[i]]=1;
00770                 for (j=NonZeroCol; j<(FSP_data->Mred-1); j++)
00771                     SLCol[j]=SLCol[j+1];
00772                 for (j=i; j<(FSP_data->Nred-1); j++)
00773                     SLRow[j]=SLRow[j+1];
00774                 FSP_data->Nred--;
00775                 FSP_data->Mred--;
00776                 }
00777             else            /* row of all zeros, also eliminated */
00778             if ((Restriction == 0) && (RowElim[SLRow[i]] != 1))
00779                 {
00780                 RowElim[SLRow[i]]=1;
00781                 for (j=i; j<(FSP_data->Nred-1); j++)
00782                     SLRow[j]=SLRow[j+1];
00783                 FSP_data->Nred--;
00784                 }
00785             }
00786         if (FSP_data->Nred == LastNred)
00787         StillChecking = 0;
00788         }
00789 
00790 
00791       /* check for columns of zeros */
00792     for (i=0; i<FSP_data->Mred; i++)
00793         {
00794         j=0;
00795         while ((j<FSP_data->Nred) && (fabs(Aorig->p[SLRow[j]][SLCol[i]]) <
00796                                                                         SMALL))
00797             j++;
00798         if (j==FSP_data->Nred)
00799             { 
00800             ColElim[SLCol[i]]=1;
00801             for (j=i; j<(FSP_data->Mred-1); j++)
00802                 SLCol[j]=SLCol[j+1];
00803             FSP_data->Mred--;
00804             i--;
00805             }
00806         }
00807 
00808      /* check for dependent rows */
00809 if (FSP_data->Mred !=0)
00810     {
00811     n      = mat_malloc(FSP_data->Mred,FSP_data->Mred-1);
00812     Atrans = mat_malloc(FSP_data->Mred,FSP_data->Mred);
00813     for (i=0; i<FSP_data->Nred; i++)
00814         for (j=0; j<FSP_data->Mred; j++)
00815             Atrans->p[j][i] = Aorig->p[SLRow[i]][SLCol[j]];
00816     for (i=FSP_data->Nred; i<FSP_data->Mred; i++)
00817         for (j=0; j<FSP_data->Mred; j++) Atrans->p[j][i] = 0;
00818 
00819     mat_null(Atrans, &nullity, n, &K2);
00820     nullity=nullity+FSP_data->Nred-FSP_data->Mred;
00821 
00822 
00823     /* This is where the b's should be checked and determined if they */
00824     /* are dependent as well.  If they are not, an error message      */
00825     /* should be displayed and the system should stop.                */
00826     /* This is probably the best place to do this, instead of at the  */
00827     /* bottom of solution_generator(), since it has the information.  */
00828     nul_count=0;
00829     while (nul_count < nullity)
00830         {
00831         i=FSP_data->Mred-FSP_data->Nred +nul_count;
00832         j=0;
00833         while ((j!=(n->rows))&&(fabs(n->p[j][i]) < SMALL))
00834             j++;
00835         if ((RowElim[SLRow[j]] != 1)&&(j!=(n->rows)))  
00836             {
00837             RowElim[SLRow[j]] = 2;
00838             for (k=j; k<(FSP_data->Nred-1); k++)
00839                 SLRow[k]=SLRow[k+1];
00840             FSP_data->Nred--;
00841             }
00842         nul_count++;
00843         }
00844     mat_free(Atrans);
00845     mat_free(n);
00846     }
00847 
00848 
00849      /* check for SpecialCase1 */
00850     for (i=0;(i<FSP_data->Nred);i++)
00851         if (fabs(btemp[SLRow[i]])<SMALL)
00852             {
00853             nonzerocol=0;
00854             j=0;
00855             Stop =FALSE;
00856             while (j<(FSP_data->Mred-1) && !Stop)
00857                 if (fabs(Aorig->p[SLRow[i]][SLCol[j]])>SMALL)
00858                     {
00859                     k=j+1;
00860                     while (!Stop && (k<FSP_data->Mred))
00861                         if (fabs(Aorig->p[SLRow[i]][SLCol[k]])>SMALL)
00862                             if (Dependency(Aorig, SLRow, FSP_data->Nred,
00863                                                         SLCol[j], SLCol[k]))
00864                                 k++;
00865                             else
00866                                 Stop=TRUE;
00867                         else
00868                             k++;
00869                     Nonzero[nonzerocol]=SLCol[j];
00870                     nonzerocol++;
00871                     j++;
00872                     }       
00873                 else
00874                     j++;
00875             if (fabs(Aorig->p[SLRow[i]][SLCol[(FSP_data->Mred-1)]])>SMALL)
00876                 {
00877                 Nonzero[nonzerocol]=SLCol[(FSP_data->Mred-1)];
00878                 nonzerocol++;
00879                 }
00880             if (nonzerocol==1)
00881                 Stop=TRUE;
00882             if (!Stop) /* Discovered a SpecialCase1 */
00883                 {
00884                 DoneRed=FALSE;
00885                 for (r=0;r<nonzerocol;r++)
00886                    ColElim[Nonzero[r]]=2;
00887                 count=0;
00888                 count2=0;
00889                 for (position=0; position<FSP_data->Mred; position++)
00890                     if (SLCol[position]!=Nonzero[count2])
00891                         {
00892                         SLCol[count]=SLCol[position];
00893                         count++;
00894                         }
00895                     else
00896                         count2++;
00897                 /* Construct new g matrix */
00898                 AElim = mat_malloc(1, nonzerocol);
00899                 n=mat_malloc(nonzerocol, nonzerocol-1);
00900                 for (r=0; r<nonzerocol;r++)
00901                     AElim->p[0][r]=Aorig->p[SLRow[i]][Nonzero[r]];
00902                 mat_null(AElim, &nullity, n, &K2);
00903 
00904                 FSP_data->Mred=FSP_data->Mred-nonzerocol;
00905                 RowElim[SLRow[i]]=1;
00906                 for (r=i; r<(FSP_data->Nred-1); r++)
00907                     SLRow[r]=SLRow[r+1];
00908                 FSP_data->Nred--;
00909                 for (m=0; m<(nonzerocol-1);m++)
00910                     {
00911                     for (r=0; r<M; r++)
00912                         Specialg ->p[*NumSpg][r]=0;
00913                     for (r=0; r<nonzerocol;r++)
00914                         Specialg ->p[*NumSpg][Nonzero[r]]=n->p[r][m];
00915                     *NumSpg=*NumSpg+1;
00916                     }
00917                 mat_free(AElim);
00918                 mat_free(n);
00919                 }
00920             }
00921 
00922     /*Check for SpecialCase2*/
00923     i=0;
00924     Stop2=FALSE;
00925     while ((i<(FSP_data->Nred-1)) && (!Stop2))
00926         {
00927         j=i+1;
00928         while ((j<FSP_data->Nred) && (!Stop2))
00929             {
00930             Stop=FALSE;
00931             Flag=FALSE;
00932             if (fabs(btemp[SLRow[i]])>SMALL)
00933                 beta= btemp[SLRow[j]]/ btemp[SLRow[i]];
00934             else
00935                 Flag=TRUE;
00936             ClassANum=0;
00937             k=0;
00938             reference=i;
00939             while ((!Stop) && (k<FSP_data->Mred))
00940                 {
00941                 Goin=FALSE;
00942                 if (fabs(Aorig->p[SLRow[i]][SLCol[k]])<SMALL)
00943                     if (!Flag)
00944                         Goin=TRUE;
00945                     else;
00946                 else
00947                     {
00948                     if (fabs((Aorig->p[SLRow[j]][SLCol[k]]/
00949                             Aorig->p[SLRow[i]][SLCol[k]])-beta)>SMALL)
00950                         Goin=TRUE;
00951                     if (Flag)
00952                         Goin=TRUE;
00953                     }
00954                 if (Goin)
00955                     {
00956                     ClassA[ClassANum]=SLCol[k];
00957                     if (ClassANum==0)
00958                         {
00959                         if (fabs(Aorig->p[SLRow[reference]][ClassA[0]])<SMALL)
00960                             {
00961                             reference=j;
00962                             if (fabs(Aorig->p[SLRow[reference]][ClassA[0]])
00963                                                                         <SMALL)
00964                                 Stop=TRUE;
00965                             }
00966                         if (!Stop)
00967                             for (r=0;r<FSP_data->Nred;r++)
00968                                 Constant[r]=Aorig->p[SLRow[r]][ClassA[0]]/
00969                                         Aorig->p[SLRow[reference]][ClassA[0]];
00970                         }
00971                     else if (fabs(Aorig->p[SLRow[reference]][ClassA[ClassANum]])
00972                                                                         <SMALL)
00973                         Stop=TRUE;
00974                     else
00975                         {
00976                         r=0;
00977                         while ((r<FSP_data->Nred) && (!Stop))
00978                             {
00979                             if (fabs((Aorig->p[SLRow[r]][ClassA[ClassANum]]/
00980                                 Aorig->p[SLRow[reference]][ClassA[ClassANum]])
00981                                                            -Constant[r])>SMALL)
00982                                 Stop=TRUE;
00983                             r++;
00984                             }
00985                         }
00986                     ClassANum++;
00987                     }
00988                 k++;
00989                 }
00990             if (!Stop)
00991                 Stop2=TRUE;
00992             j++;
00993             }
00994         i++;
00995         }
00996     if (Stop2)
00997         {
00998         DoneRed=FALSE;
00999         /* Construct new g matrix */
01000         AElim = mat_malloc(1, ClassANum);
01001         n= mat_malloc(ClassANum, ClassANum-1);
01002         for (p=0; p<ClassANum;p++)
01003             AElim->p[0][p]=Aorig->p[SLRow[reference]][ClassA[p]];
01004         mat_null(AElim, &nullity, n, &K2);
01005         for (p=0; p<(ClassANum-1);p++)
01006             {
01007             for (r=0; r<FSP_data->M; r++)
01008                 Specialg ->p[*NumSpg][r]=0;
01009             for (r=0; r<ClassANum;r++)
01010                 Specialg ->p[*NumSpg][ClassA[r]]=n->p[r][p];
01011             *NumSpg=*NumSpg+1;
01012             }
01013         FSP_data->Nred--;
01014         RowElim[SLRow[reference]]=1;
01015         for (r=0;r<ClassANum;r++)
01016             ColElim[ClassA[r]]=3;
01017         for (r=reference;r<FSP_data->Nred;r++)
01018             SLRow[r]=SLRow[(r+1)];
01019         count=0;
01020         count2=0;
01021         for (position=0; position<FSP_data->Mred; position++)
01022             if (SLCol[position]!=ClassA[count2])
01023                 {
01024                 SLCol[count]=SLCol[position];
01025                 count++;
01026                 }
01027             else
01028                 count2++;
01029         FSP_data->Mred=FSP_data->Mred-ClassANum;
01030         mat_free(AElim);
01031         mat_free(n);
01032         }
01033     }
01034 
01035 
01036      /* store the reduced A in the variable Ared, and the       */
01037      /* modified b in bred                                      */
01038 j=-1;
01039 for (i=0; i<N; i++)
01040   if (RowElim[i] == 0)
01041      {
01042      j++;
01043      bred->p[j][0]=btemp[i];
01044      m=-1;
01045      for (k=0; k<M; k++)
01046         if (ColElim[k] == 0)
01047            {
01048            m++;
01049            Ared->p[j][m] = Aorig->p[i][k];
01050            }
01051      }
01052 free (SLRow);
01053 free (SLCol);
01054 free (Nonzero);
01055 free (ClassA);  
01056 free (Constant);
01057 
01058 }
01059 
01060 
01061 
01062 /* ________________________________________________________
01063   | name:    CheckB                                        |
01064   | description:  Checks that after reducing the A, not all|
01065   |               requested workspace motions are zero     |
01066   |               (trivial motion).                        |
01067   |                                                        |
01068   |                                                        |
01069   | inputs:  b, corresponding N                            |
01070   | outputs: If it is all zeros                            |
01071   |________________________________________________________|
01072   | Authors:     Date:     Modifications:                  |
01073   |  k morganson 8/94      Created                         |
01074   |________________________________________________________| */
01075 
01076 int CheckB      (MATRIX *b, int m)
01077 {
01078 int i;
01079 
01080 i=0;
01081       /* stop checking b when a nonzero element is found */
01082 while ((i<m) && (fabs(b->p[i][0]) < SMALL))
01083    i++;
01084 
01085 if (i==m)
01086    return(0);
01087 else
01088    return(m);
01089 }
01090 
01091 
01092 
01093 /* ________________________________________________________
01094   | name:    CheckRange                                    |
01095   | description:  Checks that the original b is in the     |
01096   |               range of A.                              |
01097   |                                                        |
01098   |                                                        |
01099   | inputs:  borig, Aorig, g, RowElim, Mred                |
01100   | outputs: If it is in range                             |
01101   |________________________________________________________|
01102   | Authors:     Date:     Modifications:                  |
01103   |  k morganson 8/94      Created                         |
01104   |________________________________________________________| */
01105 
01106 int CheckRange (MATRIX * b, MATRIX * Aorig, MATRIX * g,
01107                 int   *RowElim,    int    Mred )
01108 {
01109   int i, j, k;
01110   float CheckValue, CheckTemp, CheckTemp2;
01111 /*
01112   for (i = 0; i < (Aorig -> rows); i++)
01113   {
01114     if (RowElim[i] == 2)
01115     {
01116       for (j = 0; j < (g -> rows); j++)
01117       {
01118         CheckValue = 0.0;
01119         for (k = 0; k< (Aorig -> cols); k++)
01120           CheckValue += Aorig -> p[i][k] * g -> p[j][k];
01121         CheckTemp  = fabs (b->p[i][0] - CheckValue);
01122         CheckTemp2 = .02;   
01123         if (CheckTemp > CheckTemp2)
01124           return (0);
01125       }
01126     }
01127   }
01128 */  return (1);
01129 }
01130 
01131 
01132 
01133 
01134 /* ________________________________________________________
01135   | name:    Rebuild_gs                                    |
01136   | description:  Given the created g vectors for the      |
01137   |               reduced Jacobian, this procedure adds    |
01138   |               zeros in eliminated columns and tacks on |
01139   |               the g vectors created by SpecialCase1    |
01140   |                                                        |
01141   |                                                        |
01142   | inputs:  g, ColElim, Mred, Nred, M, NumSpg, Specialg   |
01143   | outputs: g                                             |
01144   |________________________________________________________|
01145   | Authors:     Date:     Modifications:                  |
01146   |  c hacker    3/95      Created                         |
01147   |  g fries     3/95      Additional ability handling     |
01148   |                        SpecialCase1 (ie Specialg)      |
01149   |________________________________________________________| */
01150 
01151 
01152 void Rebuild_gs (Solutions *FSP_data, int *ColElim, MATRIX *Specialg,int NumSpg)
01153 {
01154   int    i,j,k;
01155   MATRIX *gtemp;
01156 
01157   gtemp = mat_cp2(FSP_data->g);
01158 
01159   k = 0;
01160   for (j = 0; j < FSP_data->M; j++)
01161   {
01162     if (ColElim[j] != 0)
01163     {
01164        for (i=0;i<FSP_data->g->rows;i++)
01165          FSP_data->g->p[i][j] = ZERO; 
01166     }
01167     else
01168     {
01169        for (i=0;i<FSP_data->g->rows;i++)
01170          FSP_data->g->p[i][j] = gtemp->p[i][k];
01171        k++;
01172     }
01173   }
01174 
01175   /*Addition of null vectors created by SpecialCase1*/
01176   for (i=(FSP_data->Mred-FSP_data->Nred+1);i<
01177                         (FSP_data->Mred-FSP_data->Nred+1+NumSpg);i++)
01178     for(j=0;j<FSP_data->M; j++)
01179         if (ColElim[j] !=0)
01180             FSP_data->g->p[i][j]=
01181                         Specialg->p[(i-FSP_data->Mred+FSP_data->Nred-1)][j];
01182             else
01183                 FSP_data->g->p[i][j]=FSP_data->g->p[0][j];
01184 
01185   mat_free(gtemp);
01186 }
01187 
01188 

Generated on Thu Jul 29 15:56:35 2004 for OpenSim by doxygen 1.3.6