matrix_skyline.c

来自「利用语言编写的有限元分析软件」· C语言 代码 · 共 1,799 行 · 第 1/5 页

C
1,799
字号
MATRIX *spC;
int *ld, min_ldi;
int  ii, ij;
int  length, length1, length2;
DIMENSIONS *d1, *d2;
int UNITS_SWITCH;

     UNITS_SWITCH = CheckUnits();
    /* [a] : Check for compatible matrix dimensions and data types */

       if((spA == NULL) || (spB == NULL))
          FatalError("In MatrixAddSkyline() : Either spA = NULL or spB = NULL",
                    (char *) NULL);

       if(spA->eRep != spA->eRep) 
          FatalError("In MatrixAddSkyline() : spA->eRep != spB->eRep",
                    (char *) NULL );

       if(spA->eType != spB->eType) 
          FatalError("In MatrixAddSkyline() : spA->eType != spB->eType",
                    (char *) NULL);

    /* [b] : Compute Skyline Profile for [A] + [B] */

       ld = iVectorAlloc( spA->iNoColumns ); 
       for(ii = 0; ii < spA->iNoColumns; ii++) 
           ld[ii] = (int) MAX (spA->uMatrix.daa[ii][0], spB->uMatrix.daa[ii][0]);

    /* [c] : Allocate Skyline Matrix for [C] : [C] = [A] + [B] */

       spC = MatrixAllocSkyline((char *)NULL,DOUBLE_ARRAY,spA->iNoRows, spA->iNoColumns, ld);

    /* [d] : Compute [C] = [A] + [B] */

       switch( UNITS_SWITCH) {
         case ON:
            for(ii = 1; ii <= spA->iNoRows; ii++)
                UnitsCopy( &(spC->spRowUnits[ii-1]), &(spA->spRowUnits[ii-1]) );
            for(ij = 1; ij <= spA->iNoColumns; ij++)
                UnitsCopy( &(spC->spColUnits[ij-1]), &(spA->spColUnits[ij-1]) );

         /* [b] : Check Units and Add Matrices : [C] = [A] + [B] */

            for(ii = 0; ii < spA->iNoColumns; ii++) {
                min_ldi = (int) MIN ( spA->uMatrix.daa[ii][0], spB->uMatrix.daa[ii][0]);
                for(ij = 1; ij <= spA->iNoColumns; ij++) {

                    d1 = UnitsMult( &(spA->spRowUnits[ii]), &(spA->spColUnits[ij-1]) );
                    d2 = UnitsMult( &(spB->spRowUnits[ii]), &(spB->spColUnits[ij-1]) );

                    if(SameUnits(d1, d2) == TRUE) {
                       if( ij <= min_ldi )
                          spC->uMatrix.daa[ii][ij] = spA->uMatrix.daa[ii][ij] 
                                                   + spB->uMatrix.daa[ii][ij];
                       else if( (spA->uMatrix.daa[ii][0] > min_ldi) && (ij <= ld[ii]) ) 
                          spC->uMatrix.daa[ii][ij] = spA->uMatrix.daa[ii][ij];
                       else if( (spB->uMatrix.daa[ii][0] > min_ldi) && (ij <= ld[ii]) ) 
                          spC->uMatrix.daa[ii][ij] = spB->uMatrix.daa[ii][ij];
                    }
                    else {
                       printf("For row No %d, column No %d \n", ii, ij);
                       FatalError(" In MatrixAddIndirectDouble(): Inconsistent Units",
                                    (char *)NULL);
                    }
                    free((char *) d1->units_name);
                    free((char *) d1);
                    free((char *) d2->units_name);
                    free((char *) d2);
                }
            }
            break;
         case OFF:
            for(ii = 0; ii < spA->iNoColumns; ii++) {
                min_ldi = (int) MIN ( spA->uMatrix.daa[ii][0], spB->uMatrix.daa[ii][0]);
                for(ij = 1; ij <= min_ldi; ij++)
                    spC->uMatrix.daa[ii][ij] = spA->uMatrix.daa[ii][ij] +
                                               spB->uMatrix.daa[ii][ij];

                if( spA->uMatrix.daa[ii][0] > min_ldi) 
                    for(ij = min_ldi+1; ij <= ld[ii]; ij++) 
                        spC->uMatrix.daa[ii][ij] = spA->uMatrix.daa[ii][ij];
                 
                if( spB->uMatrix.daa[ii][0] > min_ldi) 
                    for(ij = min_ldi+1; ij <= ld[ii]; ij++) 
                        spC->uMatrix.daa[ii][ij] = spB->uMatrix.daa[ii][ij];
            }
            break;
         default:
            break;
       }
       spC = MatrixReallocSkyline ( spC );

       free((char *) ld);
       return ( spC );
}

/*
 *  =======================================================================
 *  MatrixSubSkyline() : Subtract two Skyline Matrices
 * 
 *  Input  :  MATRIX *spA        -- Pointer to matrix data structure.
 *         :  MATRIX *spB        -- Pointer to matrix data structure.
 *  Output :  MATRIX *spC        -- Pointer to matrix differnce.
 *  =======================================================================
 */

#ifdef __STDC__
MATRIX *MatrixSubSkyline( MATRIX *spA , MATRIX *spB )
#else  /* Start case not STDC */
MATRIX *MatrixSubSkyline( spA, spB )
MATRIX *spA, *spB;
#endif /* End case not STDC */
{
MATRIX *spC;
int *ld, min_ldi;
int  ii, ij;
int  length, length1, length2;
DIMENSIONS *d1, *d2;
int UNITS_SWITCH;

     UNITS_SWITCH = CheckUnits();
    /* [a] : Check for compatible matrix dimensions and data types */

       if((spA == NULL) || (spB == NULL))
          FatalError("In MatrixSubSkyline() : Either spA = NULL or spB = NULL",
                    (char *) NULL);

       if(spA->eRep != spA->eRep) 
          FatalError("In MatrixSubSkyline() : spA->eRep != spB->eRep",
                    (char *) NULL );

       if(spA->eType != spB->eType) 
          FatalError("In MatrixSubSkyline() : spA->eType != spB->eType",
                    (char *) NULL);

    /* [b] : Compute Skyline Profile for [A] - [B] */

       ld = iVectorAlloc( spA->iNoRows ); 
       for(ii = 0; ii < spA->iNoRows; ii++) 
           ld[ii] = (int) MAX (spA->uMatrix.daa[ii][0], spB->uMatrix.daa[ii][0]);

    /* [c] : Allocate Skyline Matrix for [C] : [C] = [A] - [B] */

       spC = MatrixAllocSkyline((char *)NULL, DOUBLE_ARRAY,
                        spA->iNoRows, spA->iNoColumns, ld);

    /* [d] : Compute [C] = [A] - [B] */

       switch( UNITS_SWITCH) {
         case ON:
            for(ii = 1; ii <= spA->iNoRows; ii++)
                UnitsCopy( &(spC->spRowUnits[ii-1]), &(spA->spRowUnits[ii-1]) );
            for(ij = 1; ij <= spA->iNoColumns; ij++)
                UnitsCopy( &(spC->spColUnits[ij-1]), &(spA->spColUnits[ij-1]) );

         /* [b] : Check Units and Sub Matrices : [C] = [A] - [B] */

            for(ii = 0; ii < spA->iNoRows; ii++) {
                min_ldi = (int) MIN ( spA->uMatrix.daa[ii][0], spB->uMatrix.daa[ii][0]);
                for(ij = 1; ij <= spA->iNoColumns; ij++) {

                    d1 = UnitsMult( &(spA->spRowUnits[ii]), &(spA->spColUnits[ij-1]) );
                    d2 = UnitsMult( &(spB->spRowUnits[ii]), &(spB->spColUnits[ij-1]) );

                    if(SameUnits(d1, d2) == TRUE) {
                       if( ij <= min_ldi )
                          spC->uMatrix.daa[ii][ij] = spA->uMatrix.daa[ii][ij]
                                                   - spB->uMatrix.daa[ii][ij];
                       else if( (spA->uMatrix.daa[ii][0] > min_ldi) && (ij <= ld[ii]) ) 
                          spC->uMatrix.daa[ii][ij] = spA->uMatrix.daa[ii][ij];
                       else if( (spB->uMatrix.daa[ii][0] > min_ldi) && (ij <= ld[ii]) ) 
                          spC->uMatrix.daa[ii][ij] = -spB->uMatrix.daa[ii][ij];
                    }
                    else {
                       printf("For row No %d, column No %d \n", ii, ij);
                       FatalError("In MatrixSubIndirectDouble(): Inconsistent Units",
                                   (char *)NULL);
                    }
                    free((char *) d1->units_name);
                    free((char *) d1);
                    free((char *) d2->units_name);
                    free((char *) d2);
                }
            }
            break;
         case OFF:
            for(ii = 0; ii < spA->iNoRows; ii++) {
                min_ldi = (int) MIN ( spA->uMatrix.daa[ii][0], spB->uMatrix.daa[ii][0]);
                for(ij = 1; ij <= min_ldi; ij++)
                    spC->uMatrix.daa[ii][ij] = spA->uMatrix.daa[ii][ij] -
                                               spB->uMatrix.daa[ii][ij];

                if( spA->uMatrix.daa[ii][0] > min_ldi) 
                    for(ij = min_ldi+1; ij <= ld[ii]; ij++) 
                        spC->uMatrix.daa[ii][ij] = spA->uMatrix.daa[ii][ij];
                 
                if( spB->uMatrix.daa[ii][0] > min_ldi) 
                    for(ij = min_ldi+1; ij <= ld[ii]; ij++) 
                        spC->uMatrix.daa[ii][ij] = -spB->uMatrix.daa[ii][ij];
            }
            break;
         default:
            break;
       }
       spC = MatrixReallocSkyline ( spC );

       free((char *) ld);
       return ( spC );
}

/*
 *  =======================================================================
 *  MatrixMultSkyline() : Multiply two Skyline Matrices.
 * 
 *  Input  :  MATRIX *spA -- Pointer to matrix data structure [A].
 *         :  MATRIX *spB -- Pointer to matrix data structure [B].
 *  Output :  MATRIX *spC -- Pointer to matrix product [C] = [A]*[B]
 * 
 *  Note : If [A] and [B] are symmetric, then [A]*[B] is symmetric only iff
 *         [A]*[B] = [B]*[A]. In general, this condition will not hold -- so
 *         we store matrix product [ma]*[mb] in INDIRECT form.
 *  =======================================================================
 */

#ifdef __STDC__
MATRIX *MatrixMultSkyline( MATRIX *spA, MATRIX *spB )
#else  /* Start case not STDC */
MATRIX *MatrixMultSkyline( spA, spB )
MATRIX *spA;
MATRIX *spB;
#endif /* End case not STDC */
{
MATRIX *spC;
int ii, ij, ik, init;
int im, in, kka, kkb;
int  length1, length2, length;
DIMENSIONS *d1, *d2, *d3, *d4, *d5;
int UNITS_SWITCH;

#define DEBUG

#ifdef DEBUG
       printf("*** Enter MatrixMultSkyline()\n");
#endif
     UNITS_SWITCH = CheckUnits();

    /* [a] : Check for compatible matrix dimensions and data types etc... */

       if((spA == NULL) || (spB == NULL))
          FatalError("In MatrixMultSkyline() : Either spA = NULL or spB = NULL",
                    (char *) NULL);

       if(spA->eRep != spB->eRep) 
          FatalError("In MatrixMultSkyline() : spA->eRep != spB->eRep",
                    (char *) NULL);

       if(spA->eType != spB->eType) 
          FatalError("In MatrixMultSkyline() : spA->eType != spB->eType",
                    (char *) NULL);

       if(spA->iNoColumns != spB->iNoRows) 
          FatalError("In MatrixMultSkyline() : spA->iNoColumns != spB->iNoRows",
                    (char *) NULL);

    /* [b] : Allocate Memory for Matrix Product */

       spC = MatrixAllocIndirect( (char *) NULL, DOUBLE_ARRAY,
                               spA->iNoRows, spB->iNoColumns); 

    /* [c] : Compute elements of matrix product */

       switch( UNITS_SWITCH) {
         case ON: 
            for(ii = 1; ii <= spA->iNoRows; ii++) {
               for(ij = 1; ij <= spB->iNoColumns; ij++) {

                  d4 = (DIMENSIONS *) MyCalloc( 1, sizeof(DIMENSIONS) );
                  ZeroUnits(d4);

                  init = (int) MAX((ii - spA->uMatrix.daa[ii-1][0]+1),
                                   (ij - spB->uMatrix.daa[ij-1][0]+1));

                  for(ik = 1; ik <= spA->iNoColumns; ik++) {

                     d1 = UnitsMult(&(spA->spRowUnits[ii-1]),&(spA->spColUnits[ik-1]));
                     d2 = UnitsMult(&(spB->spRowUnits[ik-1]),&(spB->spColUnits[ij-1]));
                     d3 = UnitsMult(d1,d2);

                     if( ik == 1  &&  d3->units_name != (char *)NULL )
                         UnitsCopy(d4, d3);

                     if( ik >= init ) {
                        if( SameUnits(d3,d4) == TRUE ) {

                           im  = (int) MAX(ik,ii);
                           kka = (int) MIN(ik,ii);

                           in  = (int) MAX(ik,ij);
                           kkb = (int) MIN(ik,ij);

                           if((im-kka+1) <= spA->uMatrix.daa[ im-1 ][0] &&
                              (in-kkb+1) <= spB->uMatrix.daa[ in-1 ][0] )
                               spC->uMatrix.daa[ ii-1 ][ ij-1 ] +=
                                  spA->uMatrix.daa[im-1][im-kka+1]
                                 *spB->uMatrix.daa[in-1][in-kkb+1];
                        }
                        else
                          FatalError("In MatrixMultSkyline(): Inconsistent Units",(char *)NULL);
                     }
                     free((char *) d1->units_name);
                     free((char *) d1);
                     free((char *) d2->units_name);
                     free((char *) d2);
                     free((char *) d3->units_name);
                     free((char *) d3);
                  }
                  free((char *) d4->units_name);
                  free((char *) d4);
               }
            }

            for(ii = 1; ii <=  spC->iNoRows; ii++) 
               UnitsMultRep( &(spC->spRowUnits[ii-1]), &(spB->spRowUnits[0]),&(spA->spRowUnits[ii-1]));

           for(ij = 1; ij <= spC->iNoColumns; ij++)
               UnitsMultRep( &(spC->spColUnits[ij-1]), &(spA->spColUnits[0]),&(spB->spColUnits[ij-1]));
           break;
        case OFF:
            for(ii = 1; ii <= spA->iNoRows; ii++) {
               for(ij = 1; ij <= spB->iNoColumns; ij++) {
                  init = (int) MAX((ii - spA->uMatrix.daa[ii-1][0]+1),
                                   (ij - spB->uMatrix.daa[ij-1][0]+1));
                  for(ik = init; ik <= spA->iNoColumns; ik++) {
                     im  = (int) MAX(ik,ii);
                     kka = (int) MIN(ik,ii);

                     in  = (int) MAX(ik,ij);
                     kkb = (int) MIN(ik,ij);

                     if((im-kka+1) <= spA->uMatrix.daa[im-1][0] &&
                        (in-kkb+1) <= spB->uMatrix.daa[in-1][0] )
                         spC->uMatrix.daa[ ii-1 ][ ij-1 ] +=
                         spA->uMatrix.daa[im-1][im-kka+1]*spB->uMatrix.daa[in-1][in-kkb+1];
                  }
               }
            }
           break;
        default:
           break;
      }

#ifdef DEBUG
       printf("*** Leaving MatrixMultSkyline()\n");
#endif

      return (spC);
}
#undef DEBUG

/*

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?