Ticket #1505: removing_m4ri.patch
| File removing_m4ri.patch, 70.9 kB (added by malb, 1 year ago) |
|---|
-
/dev/null
old new 1 /******************************************************************************2 *3 * M4RI: Method of the Four Russians Inversion4 *5 * Copyright (C) 2007 Gregory Bard <gregory.bard@ieee.org>6 *7 * Distributed under the terms of the GNU General Public License (GPL)8 *9 * This code is distributed in the hope that it will be useful,10 * but WITHOUT ANY WARRANTY; without even the implied warranty of11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU12 * General Public License for more details.13 *14 * The full text of the GPL is available at:15 *16 * http://www.gnu.org/licenses/17 ******************************************************************************/18 19 #include "brilliantrussian.h"20 #include <stdlib.h>21 22 int forceNonZero2PackedFlex(packedmatrix *m, int xstart, int xstop, int y) {23 int i;24 25 for (i=xstart; i<=xstop; i++) {26 if (readPackedCell(m, i, y)==1) {27 if (i!=xstart) rowSwapPacked(m, i, xstart);28 return YES;29 }30 }31 32 return NO;33 }34 35 36 int prepPackedFlex(packedmatrix *m, int ai, int k) {37 int pc; /* pivot column */38 int tr; /* target row */39 int good;40 41 int rank = 0;42 43 for (pc=ai; pc<min(ai+k,m->cols); pc++) {44 /* Step one, find a pivot row in this column.*/45 good=forceNonZero2PackedFlex(m, pc, min( ai+k*3-1, m->rows-1 ), pc);46 47 if (good==NO) return rank;48 49 for (tr=ai; tr<min(ai+k*3, m->rows); tr++) {50 /* Step two, add this pivot row to other rows as needed. */51 if (tr==pc) continue;52 53 if (readPackedCell(m, tr, pc)==0) continue;54 55 rowAddPackedOffset(m, pc, tr, ai);56 }57 rank++;58 }59 60 return rank;61 }62 63 void combineFlex( packedmatrix * s1, int row1, int startblock1,64 packedmatrix * s2, int row2, int startblock2,65 packedmatrix * dest, int row3, int startblock3 ) {66 int wide=s1->width - startblock1;67 int i;68 69 word *b1_ptr = s1->values + startblock1 + s1->rowswap[row1];70 word *b2_ptr = s2->values + startblock2 + s2->rowswap[row2];71 word *b3_ptr;72 73 /* this is a quite likely case, and we treat is specially to ensure74 cache register friendlyness. (Keep in mind that the x86 has only75 four general purpose registers) */76 if( dest == s1 && row1 == row3 && startblock1 == startblock3) {77 78 /* A fair amount of time is spent in iterating i, thus we lower79 the burden a bit here.80 */81 if(wide%2==0) {82 for(i = wide>>1 ; i > 0 ; i--) {83 *b1_ptr++ ^= *b2_ptr++;84 *b1_ptr++ ^= *b2_ptr++;85 }86 return;87 88 } else {89 for(i = wide ; i > 0 ; i--) {90 *b1_ptr++ ^= *b2_ptr++;91 }92 return;93 94 }95 96 } else {97 b3_ptr = dest->values + startblock3 + dest->rowswap[row3];98 99 for(i = 0 ; i < wide ; i++) {100 *b3_ptr++ = *b1_ptr++ ^ *b2_ptr++;101 }102 return;103 }104 }105 106 void makeTablePackedFlex( packedmatrix *m, int ai, int k,107 packedmatrix *tablepacked, int *lookuppacked, int full) {108 int homeblock= full ? 0 : ai/RADIX;109 int i, rowneeded, id;110 int twokay= TWOPOW(k);111 112 lookuppacked[0]=0;113 114 for (i=1; i<twokay; i++) {115 rowneeded=codebook[k]->inc[i-1]+ai;116 117 id=codebook[k]->ord[i];118 119 lookuppacked[id]=i;120 121 combineFlex( m, rowneeded, homeblock,122 tablepacked, i-1, homeblock,123 tablepacked, i, homeblock);124 }125 }126 127 128 inline int getValueFlex(packedmatrix *m, int x, int y, int k) {129 int truerow = m->rowswap[x];130 int block;131 int spot;132 133 word temp;134 135 word *values = m->values;136 137 /**138 * there are two possible situations. Either all bits are in one139 * word or they are spread across two words.140 */141 142 if ( (y%RADIX + k -1 ) < RADIX ) {143 /**144 * everything happens in one word here145 */146 temp = values[ y / RADIX + truerow ]; // get the value147 temp <<= y%RADIX; // clear upper bits148 temp >>= RADIX - k; // clear lower bits and move to correct position.149 return (int)temp;150 151 } else {152 /**153 * two words are affected154 */155 block = y / RADIX + truerow; // correct block156 spot = (y + k ) % RADIX; // correct offset157 // make room by shifting spot times to the right, and add stuff from the second word158 temp = (values[block] << spot) | ( values[block + 1] >> (RADIX - spot) );159 return ((int)temp & ((1<<k)-1)); // clear upper bits and return160 }161 }162 163 void processRowPackedFlex(packedmatrix *m, int row, int homecol, int k, packedmatrix *tablepacked, int *lookuppacked) {164 int blocknum=homecol/RADIX;165 166 int value=getValueFlex(m, row, homecol, k);167 168 int tablerow=lookuppacked[value];169 170 combineFlex( m, row, blocknum,171 tablepacked, tablerow, blocknum,172 m, row, blocknum);173 }174 175 void processPackedFlex(packedmatrix *m, int startrow, int stoprow, int startcol, int k, packedmatrix *tablepacked, int *lookuppacked) {176 int i;177 int blocknum=startcol/RADIX;178 int value;179 int tablerow;180 word *b1_ptr,*b2_ptr;181 182 // for optimization reasons we distinguish several cases here.183 184 switch(m->width - startcol/RADIX) {185 186 case 1:187 // no loop needed as only one block is operated on.188 for (i=startrow; i<=stoprow; i++) {189 value=getValueFlex(m, i, startcol, k);190 tablerow=lookuppacked[value];191 b1_ptr = m->values + blocknum + m->rowswap[i];192 b2_ptr = tablepacked->values + blocknum + tablepacked->rowswap[tablerow];193 *b1_ptr ^= *b2_ptr;194 }195 break;196 197 case 2:198 // two blocks, no loop199 for (i=startrow; i<=stoprow; i++) {200 value=getValueFlex(m, i, startcol, k);201 tablerow=lookuppacked[value];202 b1_ptr = m->values + blocknum + m->rowswap[i];203 b2_ptr = tablepacked->values + blocknum + tablepacked->rowswap[tablerow];204 *b1_ptr++ ^= *b2_ptr++;205 *b1_ptr ^= *b2_ptr;206 207 }208 break;209 210 default:211 // the real deal more than two blocks.212 for (i=startrow; i<=stoprow; i++) {213 processRowPackedFlex(m, i, startcol, k, tablepacked, lookuppacked);214 }215 break;216 }217 218 }219 220 int doAByteColumnFlex(packedmatrix *m, int full, int k, int ai,221 packedmatrix *tablepacked, int *lookuppacked) {222 int submatrixrank;223 224 /*225 * Stage 1: Denote the first column to be processed in a given226 * iteration as a_i . Then, perform Gaussian elimination on the227 * first 3k rows after and including the i-th row to produce an228 * identity matrix in $a_{(i,i)} ... a_{(i+k-1),(i+k-1)}$ , and229 * zeroes in $a_{(i+k),i} ... a_{(i+3k-1),(i+k-1)}$.230 */231 232 submatrixrank=prepPackedFlex(m, ai, k);233 234 235 if (submatrixrank!=k) return submatrixrank;236 237 /*238 * Stage 2: Construct a table consisting of the 2k binary strings of239 * length k in a Gray Code. Thus with only 2k vector additions, all240 * possible linear combinations of these k rows have been241 * precomputed.242 */243 244 makeTablePackedFlex(m, ai, k, tablepacked, lookuppacked, 0);245 246 247 /*248 * Stage 3: One can rapidly process the remaining rows from i + 3k249 * until row m (the last row) by using the table. For example,250 * suppose the jth row has entries $a_{(j,i)} ... a_{(j,i+k-1)}$ in251 * the columns being processed. Selecting the row of the table252 * associated with this k-bit string, and adding it to row j will253 * force the k columns to zero, and adjust the remaining columns254 * from i + k to n in the appropriate way, as if Gaussian255 * Elimination had been performed.256 */257 258 processPackedFlex(m, ai+k*3, m->rows-1, ai, k,259 tablepacked, lookuppacked);260 261 /* While the above form of the algorithm will reduce a system of262 * boolean linear equations to unit upper triangular form, and thus263 * permit a system to be solved with back substitution, the M4RI264 * algorithm can also be used to invert a matrix, or put the system265 * into reduced row echelon form (RREF). Simply run Stage 3 on rows266 * 0 ... i - 1 as well as on rows i + 3k · · · m. This only affects267 * the complexity slightly, changing the 2.5 coeffcient to 3268 */269 270 if (full==YES) processPackedFlex(m, 0, ai-1, ai, k,271 tablepacked, lookuppacked);272 273 return submatrixrank;274 }275 276 int fourRussiansPackedFlex(packedmatrix *m, int full, int k,277 packedmatrix *tablepacked, int *lookuppacked) {278 int i, submatrixrank;279 int stop=min(m->rows, m->cols);280 int lastokay=-1;281 282 int rank = 0;283 284 for (i=0; i<stop; i+=k) {285 // not enough room for M4RI left.286 if ( ((i+k*3-1)>=m->rows) || ((i+k-1)>=m->cols) ) {287 return rank + gaussianPackedDelayed(m, lastokay+1, full);288 }289 290 submatrixrank=doAByteColumnFlex(m, full, k, i, tablepacked, lookuppacked);291 292 if (submatrixrank!=k) {293 // not full rank, use Gaussian elimination :-(294 return rank + gaussianPackedDelayed(m, lastokay+1, full);295 }296 297 lastokay=i+k-1;298 299 rank += submatrixrank;300 }301 302 return rank;303 }304 305 int simpleFourRussiansPackedFlex(packedmatrix *m, int full, int k) {306 int size=m->cols;307 int twokay=TWOPOW(k);308 309 packedmatrix *mytable=createPackedMatrix(twokay, size);310 311 int *mylookups=(int *)safeCalloc(twokay, sizeof(int));312 313 int rank=fourRussiansPackedFlex(m, full, k, mytable, mylookups);314 315 free(mylookups);316 317 destroyPackedMatrix(mytable);318 319 return rank;320 }321 322 packedmatrix *invertPackedFlexRussian(packedmatrix *m,323 packedmatrix *identity, int k) {324 packedmatrix *big=concatPacked(m, identity);325 int size=m->cols;326 int twokay=TWOPOW(k);327 int i;328 packedmatrix *mytable=createPackedMatrix(twokay, size*2);329 330 int *mylookups=(int *)safeCalloc(twokay, sizeof(int));331 int rank;332 packedmatrix *answer;333 334 rank=fourRussiansPackedFlex(big, YES, k, mytable, mylookups);335 336 for(i=0; i < size; i++) {337 if (!readPackedCell(big, i,i )) {338 answer=NULL;339 break;340 }341 }342 if (i == size)343 answer=copySubMatrixPacked(big, 0, size, size-1, size*2-1);344 345 free(mylookups);346 destroyPackedMatrix(mytable);347 destroyPackedMatrix(big);348 349 return answer;350 }351 352 packedmatrix *m4rmTransposePacked(packedmatrix *A, packedmatrix *B, int k) {353 packedmatrix *AT, *BT, *CT, *C;354 355 if(A->cols != B->rows) die("A cols need to match B rows");356 357 AT = transposePacked(A);358 BT = transposePacked(B);359 360 CT = m4rmPacked(BT,AT,k);361 362 destroyPackedMatrix(AT);363 destroyPackedMatrix(BT);364 365 C = transposePacked(CT);366 destroyPackedMatrix(CT);367 return C;368 }369 370 371 packedmatrix *m4rmPacked(packedmatrix *A, packedmatrix *B, int k) {372 int i,j;373 int a,b,c;374 unsigned int x;375 packedmatrix *C;376 int *lookuppacked;377 packedmatrix *T;378 379 if(A->cols != B->rows) die("A cols need to match B rows");380 381 a = A->rows;382 b = A->cols;383 c = B->cols;384 385 T =createPackedMatrix(TWOPOW(k), c);386 lookuppacked = (int *)safeCalloc(TWOPOW(k), sizeof(int));387 388 C = createPackedMatrix(a,c);389 390 for(i=0 ; i < b/k ; i++) {391 392 //Make a Gray Code table of all the 2^k linear combinations of the k rows of Bi .393 //Call the xth row Tx .394 makeTablePackedFlex( B, i*k, k, T, lookuppacked, 1);395 396 for(j = 0; j<a ; j++) {397 398 //Read the entries aj,(i-1)k+1 , aj,(i-1)k+2 , . . . , aj,(i-1)k+k .399 //Let x be the k bit binary number formed by the concatenation of aj,(i-1)k+1 , . . . , aj,ik .400 x = lookuppacked[getValueFlex(A, j, i*k, k)];401 402 //for h = 1, 2, . . . , c do403 // Calculate Cjh = Cjh + Txh.404 combineFlex(C,j,0, T,x,0, C,j,0 );405 }406 }407 408 //handle rest409 if (b%k) {410 makeTablePackedFlex( B, b/k * k , b%k, T, lookuppacked, 1);411 412 for(j = 0; j<a ; j++) {413 x = lookuppacked[getValueFlex(A, j, i*k, b%k)];414 combineFlex(C,j,0, T,x,0, C,j,0);415 }416 }417 destroyPackedMatrix(T);418 free(lookuppacked);419 return C;420 } -
/dev/null
old new 1 #ifndef BRILLIANTRUSSIAN_H2 #define BRILLIANTRUSSIAN_H3 4 /******************************************************************************5 *6 * M4RI: Method of the Four Russians Inversion7 *8 * Copyright (C) 2007 Gregory Bard <gregory.bard@ieee.org>9 *10 * Distributed under the terms of the GNU General Public License (GPL)11 *12 * This code is distributed in the hope that it will be useful,13 * but WITHOUT ANY WARRANTY; without even the implied warranty of14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU15 * General Public License for more details.16 *17 * The full text of the GPL is available at:18 *19 * http://www.gnu.org/licenses/20 ******************************************************************************/21 22 23 #include <math.h>24 #include <string.h>25 #include "packedmatrix.h"26 27 #define TWOPOW(i) (1<<(i))28 29 /**30 * Finds a pivot row between xstart and xstop. The column where this31 * pivot is search is y. Returns YES if such a pivot row was32 * found. Also, the appropriate row is swapped to the top (== xstart).33 *34 * INPUT:35 * m -- matrix to operate on36 * xstart -- start row37 * xstop -- stop row (including)38 * y -- column to read39 *40 * OUTPUT:41 * YES if a pivot row was found42 */43 44 int forceNonZero2PackedFlex(packedmatrix *m, int xstart, int xstop, int y);45 46 47 /***************************************************/48 49 /**50 * Performs Gaussian elimination on a submatrix of 3k x k starting at51 * point (homepoint, homepoint) of m.52 *53 * INPUT:54 * m -- matrix to operate on55 * homepoint -- row,col where to start56 * k -- the parameter k of M4RI57 *58 * OUTPUT:59 * returns rank of 3k x k submatrix.60 */61 62 int prepPackedFlex(packedmatrix *m, int ai, int k);63 64 /** Adds row1 of s1, starting with col1 to the end, to row2 of s2,65 * starting with col2 to the end. This gets stored in dest, in row3,66 * starting with col367 *68 * row3[col3:] = row1[col1:] + row2[col2:]69 *70 */71 72 void combineFlex( packedmatrix * s1, int row1, int startblock1,73 packedmatrix * s2, int row2, int startblock2,74 packedmatrix * dest, int row3, int startblock3 );75 76 /*77 * Constructs all possible 2^k row combinations using the gray code78 * table.79 *80 * INPUT:81 * m -- matrix to operate on82 * ai -- the starting position83 * k -- the k parameter of M4RI84 * tablepacked -- prealloced matrix of dimension 2^k x m->cols85 * lookuppacked -- prealloced table of length 2^k86 * full -- touch columns before ai?87 *88 */89 90 void makeTablePackedFlex( packedmatrix *m, int ai, int k, packedmatrix *tablepacked, int *lookuppacked, int full);91 92 /**93 * returns k bits/entries starting at m[x,y].94 *95 * WARNING: Precondition is k < RADIX96 */97 98 inline int getValueFlex(packedmatrix *m, int x, int y, int k);99 100 /**101 *102 * Adds the correct row from tablepacked to the row 'row' in 'm' starting at homecol.103 *104 * INPUT:105 * m -- matrix to operate on106 * row -- the row which is operated on107 * homecol -- starting column for addition108 * k -- M4RI parameter, used for gray table lookup109 * tablepacked -- contains the correct row to be added110 * lookuptable -- contains row number to be addede111 */112 113 void processRowPackedFlex(packedmatrix *m, int row, int homecol, int k, packedmatrix *tablepacked, int *lookuppacked);114 115 /*116 * Iterates proccessPackedRowFlex from startrow to stoprow.117 */118 119 void processPackedFlex(packedmatrix *m, int startrow, int stoprow, int startcol, int k, packedmatrix *tablepacked, int *lookuppacked);120 121 /**122 * This is the actual heart of the M4RI algorithm.123 *124 */125 126 int doAByteColumnFlex(packedmatrix *m, int full, int k, int ai, packedmatrix *tablepacked, int *lookuppacked);127 128 /*129 *130 *131 */132 133 int fourRussiansPackedFlex(packedmatrix *m, int full, int k, packedmatrix *tablepacked, int *lookuppacked);134 135 /**136 * Top level function to call for M4RI137 */138 139 int simpleFourRussiansPackedFlex(packedmatrix *m, int full, int k);140 141 142 /**143 * Inverts the matrix m using the M4RI algorithm. To avoid recomputing144 * the identity matrix over and over again, I may be passed in as145 * identity parameter.146 */147 148 packedmatrix *invertPackedFlexRussian(packedmatrix *m, packedmatrix *identity, int k);149 150 151 packedmatrix *m4rmPacked(packedmatrix *A, packedmatrix *B, int k);152 153 packedmatrix *m4rmTransposePacked(packedmatrix *A, packedmatrix *B, int k);154 155 #endif //BRILLIANTRUSSIAN_H -
/dev/null
old new 1 /**2 * gray code generation used by the M4RI algorithm.3 *4 * AUTHOR: malb5 */6 7 /******************************************************************************8 *9 * M4RI: Method of the Four Russians Inversion10 *11 * Copyright (C) 2007 Gregory Bard <gregory.bard@ieee.org>12 * Copyright (C) 2007 Martin Albrecht <malb@informatik.uni-bremen.de>13 *14 * Distributed under the terms of the GNU General Public License (GPL)15 *16 * This code is distributed in the hope that it will be useful,17 * but WITHOUT ANY WARRANTY; without even the implied warranty of18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU19 * General Public License for more details.20 *21 * The full text of the GPL is available at:22 *23 * http://www.gnu.org/licenses/24 ******************************************************************************/25 26 #include "grayflex.h"27 #include <stdlib.h>28 #include <stdio.h>29 30 code **codebook;31 const int MAXKAY = 16;32 33 void printBitString(int number, int length){34 int i;35 for(i=length-1 ; i>=0; i--) {36 ((1<<i) & number) ? printf("1") : printf("0");37 }38 printf("\n");39 }40 41 int swap_bits(int v,int length) {42 unsigned int r = v; // r will be reversed bits of v; first get LSB of v43 int s = length - 1; // extra shift needed at end44 45 for (v >>= 1; v; v >>= 1)46 {47 r <<= 1;48 r |= v & 1;49 s--;50 }51 r <<= s;52 return r;53 }54 55 int grayCode(int number, int length) {56 int lastbit = 0;57 int res = 0;58 int i,bit;59 for(i=length-1; i>=0; i--) {60 bit = number & (1<<i);61 res |= ((lastbit>>1) ^ bit);62 lastbit = bit;63 };64 return swap_bits(res,length) & ((1<<length)-1);65 //return res;66 }67 68 void buildCodeFlex(int *ord, int *inc, int length) {69 int i,j;70 71 // this one is easy.72 for(i=0 ; i < TWOPOW(length) ; i++) {73 ord[i] = grayCode(i,length);74 }75 76 for(i = length ; i>0 ; i--) {77 for(j=1 ; j < TWOPOW(i) + 1 ; j++) {78 inc[j *TWOPOW(length-i) -1 ] = length - i;79 }80 }81 }82 83 void buildAllCodes() {84 int k;85 codebook=calloc(MAXKAY+1, sizeof(code *));86 87 for(k=1 ; k<MAXKAY+1; k++) {88 codebook[k] = (code *)calloc(sizeof(code),1);89 codebook[k]->ord =(int *)calloc(TWOPOW(k),sizeof(int));90 codebook[k]->inc =(int *)calloc(TWOPOW(k),sizeof(int));91 buildCodeFlex(codebook[k]->ord, codebook[k]->inc, k);92 }93 }94 95 void destroyAllCodes() {96 int i;97 for(i=1; i<MAXKAY+1; i++) {98 free(codebook[i]->inc);99 free(codebook[i]->ord);100 free(codebook[i]);101 }102 free(codebook);103 } -
/dev/null
old new 1 #ifndef GRAYFLEX_H2 #define GRAYFLEX_H3 4 /**5 * gray code generation used by the M4RI algorithm.6 *7 * AUTHOR: malb8 */9 10 /******************************************************************************11 *12 * M4RI: Method of the Four Russians Inversion13 *14 * Copyright (C) 2007 Gregory Bard <gregory.bard@ieee.org>15 * Copyright (C) 2007 Martin Albrecht <malb@informatik.uni-bremen.de>16 *17 * Distributed under the terms of the GNU General Public License (GPL)18 *19 * This code is distributed in the hope that it will be useful,20 * but WITHOUT ANY WARRANTY; without even the implied warranty of21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU22 * General Public License for more details.23 *24 * The full text of the GPL is available at:25 *26 * http://www.gnu.org/licenses/27 ******************************************************************************/28 29 struct codestruct {30 int *ord;31 int *inc;32 };33 34 typedef struct codestruct /*renamed as*/ code;35 36 extern code **codebook;37 38 #define TWOPOW(i) (1<<(i))39 40 void printBitString(int number, int length);41 42 /**43 * swaps length bits in v naively.44 *45 * WARNING: Uppper bits of return value may contain garbage after46 * operation.47 */48 int swap_bits(int v,int length);49 50 /**51 * Returns the 'number'-th gray code entry for a gray code of length52 * $2^{length}$.53 *54 * INPUT:55 * number -- index in the gray code table56 * length -- length of the gray code57 *58 * OUTPUT:59 * number-th gray code entry60 *61 * AUTHOR: malb62 *63 * THANKS: Soroosh Yazdani explained the repeated sum idea to me.64 *65 */66 67 int grayCode(int number, int length);68 69 /**70 * Fills in 'ord' and 'inc' with gray code data for a gray code of71 * length $2^{length}$.72 *73 * INPUT:74 * ord -- will hold gray code data, must be preallocated with correct size75 * inc -- will hold some increment data, must be preallocated with correct size76 *77 * AUTHOR: malb78 *79 * THANKS: Robert Miller had the idea for a non-recursive implementation.80 *81 */82 83 void buildCodeFlex(int *ord, int *inc, int length);84 85 void buildAllCodes();86 87 void destroyAllCodes();88 89 #endif //GRAYFLEX_H -
/dev/null
old new 1 /**2 * Include this file if you which to use this M4RI implementation and configure as you wish.3 *4 * AUTHOR: malb5 */6 7 /******************************************************************************8 *9 * M4RI: Method of the Four Russians Inversion10 *11 * Copyright (C) 2006, 2007 Gregory Bard <bardg@math.umd.edu>12 *13 * Distributed under the terms of the GNU General Public License (GPL)14 *15 * This code is distributed in the hope that it will be useful,16 * but WITHOUT ANY WARRANTY; without even the implied warranty of17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU18 * General Public License for more details.19 *20 * The full text of the GPL is available at:21 *22 * http://www.gnu.org/licenses/23 ******************************************************************************/24 25 #if ! defined M4RI_H26 #define M4RI_H27 28 #include <stdio.h>29 #include <stdlib.h>30 #include <math.h>31 #include "watch.h"32 #include "packedmatrix.h"33 #include "brilliantrussian.h"34 35 #endif //M4RI_H -
/dev/null
old new 1 /******************************************************************************2 *3 * M4RI: Method of the Four Russians Inversion4 *5 * Copyright (C) 2007 Gregory Bard <gregory.bard@ieee.org>6 *7 * Distributed under the terms of the GNU General Public License (GPL)8 *9 * This code is distributed in the hope that it will be useful,10 * but WITHOUT ANY WARRANTY; without even the implied warranty of11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU12 * General Public License for more details.13 *14 * The full text of the GPL is available at:15 *16 * http://www.gnu.org/licenses/17 ******************************************************************************/18 19 #include <stdio.h>20 #include <stdlib.h>21 #include "matrix.h"22 23 /***************************************************/24 /***************************************************/25 void die(char *errormessage) {26 /*This function prints the error message and exits27 the program.*/28 29 fprintf(stderr, "\a%s\n", errormessage);30 exit(1);31 }32 33 /***************************************************/34 /***************************************************/35 int min ( int a, int b) {36 if (a<=b) return a;37 else return b;38 }39 40 /***************************************************/41 /***************************************************/42 43 /* MEMLEAK, use free */44 void *safeCalloc( int count, int size ) {45 /* this function calls calloc with the given inputs,46 but dies with an error message if a NULL is returned */47 48 void *newthing=calloc( count, size );49 if (newthing==NULL) {50 die("calloc returned NULL");51 return NULL; /* unreachable. */52 }53 else return newthing;54 }55 56 /***************************************************/57 /***************************************************/58 59 /* MEMLEAK, use free */60 void *safeMalloc( int count, int size ) {61 /* this function calls malloc with the inputs, which are62 to be provided in calloc notation. If the result is63 NULL, the program dies with an error message.*/64 65 void *newthing=malloc( count*size );66 if (newthing==NULL) {67 die("malloc returned NULL");68 return NULL; /* unreachable */69 }70 else return newthing;71 }72 73 /***************************************************/74 /***************************************************/75 76 /* MEMLEAK (see destroyMatrix) */77 matrix *createMatrix( int rows, int cols) {78 matrix *newmatrix=(matrix *)safeMalloc(1,sizeof(matrix));79 80 bit *newcells=(bit *)safeCalloc(rows*cols,sizeof(bit));81 int *newrowswap=(int *)safeMalloc(rows, sizeof(int));82 int *newcolswap=(int *)safeMalloc(cols, sizeof(int));83 int i;84 85 newmatrix->cells=newcells;86 newmatrix->rowswap=newrowswap;87 newmatrix->colswap=newcolswap;88 89 newmatrix->rows=rows;90 newmatrix->cols=cols;91 92 for (i=0; i<rows; i++) { newmatrix->rowswap[i]=i; }93 for (i=0; i<cols; i++) { newmatrix->colswap[i]=i; }94 95 return newmatrix;96 }97 98 /***************************************************/99 /***************************************************/100 void destroyMatrix(matrix *condemned) {101 if (condemned==NULL) {102 printf("\aTried to free a NULL data structure.\n");103 return;104 }105 free(condemned->cells);106 free(condemned->rowswap);107 free(condemned->colswap);108 free(condemned);109 return;110 }111 112 /***************************************************/113 /***************************************************/114 void swapRow( matrix *m, int a, int b) {115 int temp=m->rowswap[a];116 m->rowswap[a]=m->rowswap[b];117 m->rowswap[b]=temp;118 }119 120 /***************************************************/121 /***************************************************/122 void swapCol( matrix *m, int a, int b) {123 int temp=m->colswap[a];124 m->colswap[a]=m->colswap[b];125 m->colswap[b]=temp;126 }127 128 /***************************************************/129 /***************************************************/130 131 void addTrueCell(matrix *thematrix, int srow, int scol, int drow, int dcol) {132 int sindex=srow * (thematrix->cols) + scol;133 int dindex=drow * (thematrix->cols) + dcol;134 135 thematrix->cells[dindex]=136 (thematrix->cells[dindex]+thematrix->cells[sindex]) % 2;137 }138 139 /***************************************************/140 /***************************************************/141 142 void writeTrueCell(matrix *thematrix, int row, int col, bit value) {143 int index=row * (thematrix->cols) + col;144 145 thematrix->cells[index]=value;146 }147 148 /***************************************************/149 /***************************************************/150 151 void addCell(matrix *thematrix, int srow, int scol, int drow, int dcol) {152 int newsrow=thematrix->rowswap[srow];153 int newscol=thematrix->colswap[scol];154 int newdrow=thematrix->rowswap[drow];155 int newdcol=thematrix->colswap[dcol];156 157 addTrueCell(thematrix, newsrow, newscol, newdrow, newdcol);158 }159 160 /***************************************************/161 /***************************************************/162 163 void writeCell(matrix *thematrix, int row, int col, bit value) {164 int newrow=thematrix->rowswap[row];165 int newcol=thematrix->colswap[col];166 167 writeTrueCell(thematrix, newrow, newcol, value);168 }169 /***************************************************/170 /***************************************************/171 172 bit readTrueCell(matrix *thematrix, int row, int col) {173 int index=row * (thematrix->cols) + col;174 175 return thematrix->cells[index];176 }177 /***************************************************/178 /***************************************************/179 180 bit readCell(matrix *thematrix, int row, int col) {181 int newrow=thematrix->rowswap[row];182 int newcol=thematrix->colswap[col];183 184 return readTrueCell(thematrix, newrow, newcol);185 }186 187 /***************************************************/188 /***************************************************/189 190 void zeroMatrix(matrix *thematrix) {191 int i, j;192 193 for (i=0; i<thematrix->rows; i++) {194 for (j=0; j<thematrix->cols; j++) {195 writeCell(thematrix, i, j, 0);196 }197 }198 }199 200 /***************************************************/201 /***************************************************/202 203 void printMatrix(matrix *thematrix) {204 int i, j;205 206 for (i=0; i<thematrix->rows; i++) {207 printf("[ ");208 for (j=0; j<thematrix->cols; j++) {209 printf("%u ", readCell(thematrix, i,j) );210 }211 printf("]\n");212 }213 214 printf("\n");215 }216 217 /***************************************************/218 /***************************************************/219 220 bit coinFlip() {221 222 223 if (rand() < RAND_MAX/2) {224 return 0;225 } else {226 return 1;227 }228 }229 230 /***************************************************/231 /***************************************************/232 233 void fillRandomMatrix(matrix *thematrix) {234 int i, j;235 236 for (i=0; i<thematrix->rows; i++) {237 for (j=0; j<thematrix->cols; j++) {238 writeCell(thematrix, i, j, coinFlip());239 }240 }241 }242 243 /***************************************************/244 /***************************************************/245 246 void setIdentityMatrix(matrix *thematrix) {247 int i;248 int limit=min(thematrix->rows, thematrix->cols);249 250 zeroMatrix(thematrix);251 252 for (i=0; i<limit; i++) {253 writeCell(thematrix, i, i, 1);254 }255 }256 257 /***************************************************/258 /***************************************************/259 260 /* MEMLEAK, use destroyMatrix */261 matrix *concatMatrix(matrix *left, matrix *right) {262 int i,j,newwidth;263 matrix *newmatrix;264 265 if (left->rows != right->rows) {266 printf("Attempted to concat matrix of height %d with height %d.",267 left->rows, right->rows);268 die("Terminating");269 }270 271 newwidth= left->cols + right->cols;272 273 newmatrix=createMatrix(left->rows, newwidth);274 275 for (i=0; i<left->rows; i++) {276 for (j=0; j<newwidth; j++) {277 if (j<left->cols) {278 writeCell(newmatrix, i, j, readCell(left, i, j));279 } else {280 writeCell(newmatrix, i, j, readCell(right, i, j-left->cols));281 }282 }283 }284 285 return newmatrix;286 }287 288 /***************************************************/289 /***************************************************/290 291 int forceNonZero(matrix *m, int x, int y) {292 int i;293 int j=y;294 295 //for (j=y; j<m->cols; j++) {296 for (i=x; i<m->rows; i++) {297 if (readCell(m, i, j)==1) {298 if (i!=x) swapRow(m, i, x);299 if (j!=y) swapCol(m, j, y);300 return YES;301 }302 }303 //}304 305 return NO;306 }307 308 /***************************************************/309 /***************************************************/310 311 void rowAdd(matrix *m, int rowa, int rowb) {312 int i;313 314 for (i=0; i<m->cols; i++) {315 /* writeCell(m, rowb, i,316 (readCell(m, rowa, i) + readCell(m, rowb, i)) % 2 );*/317 addCell(m, rowa, i, rowb, i);318 }319 }320 321 /***************************************************/322 /***************************************************/323 324 int delayedGaussian(matrix *m, int firstcol, int full) {325 int pc; /* pivot column */326 int tr; /* target row */327 int stop=min(m->rows, m->cols);328 int good;329 330 for (pc=firstcol; pc<stop; pc++) {331 /* Step one, find a pivot row in this column.*/332 good=forceNonZero(m, pc, pc);333 if (good==NO) return NO;334 335 for (tr=( full ? 0 : pc+1 ); tr<m->rows; tr++) {336 /* Step two, add this pivot row to other rows as needed. */337 if (tr==pc) continue;338 339 if (readCell(m, tr, pc)==0) continue;340 341 rowAdd(m, pc, tr);342 }343 }344 345 return YES;346 }347 348 int gaussian(matrix *m, int full) { return delayedGaussian(m,0, full); }349 350 /***************************************************/351 /***************************************************/352 353 /* MEMLEAK, use destroyMatrix() */354 matrix *copySubMatrix(matrix *m, int rlow, int clow, int rhigh, int chigh) {355 int i,j, newrows, newcols;356 matrix *newmatrix;357 358 if (rlow>rhigh) die("Bad args to subMatrix.\n");359 if (clow>chigh) die("Bad args to subMatrix.\n");360 if (clow>m->cols) die("Bad args to subMatrix.\n");361 if (chigh>m->cols) die("Bad args to subMatrix.\n");362 if (rlow>m->rows) die("Bad args to subMatrix.\n");363 if (rhigh>m->rows) die("Bad args to subMatrix.\n");364 365 newrows=rhigh-rlow+1;366 newcols=chigh-clow+1;367 368 newmatrix=createMatrix(newrows, newcols);369 370 for (i=0; i<newrows; i++) {371 for (j=0; j<newcols; j++) {372 writeCell(newmatrix, i, j, readCell(m, i+rlow, j+clow));373 }374 }375 376 return newmatrix;377 }378 379 /***************************************************************/380 381 /* MEMLEAK, use destroyMatrix */382 matrix *cloneMatrix( matrix *a ) {383 return copySubMatrix( a, 0, 0, (a->rows)-1, (a->cols)-1);384 }385 386 /***************************************************************/387 /***************************************************************/388 389 /* MEMLEAK, use destroyMatrix */390 matrix *matrixTimesMatrix(matrix *a, matrix *b) {391 int i,j,k, total;392 matrix *newmatrix;393 394 if (a->cols!=b->rows) die("Incompatible Dimensions in Matrix Multiplic.");395 396 newmatrix=createMatrix(a->rows, b->cols);397 398 for (i=0; i<a->rows; i++) {399 for (j=0; j<b->cols; j++) {400 total=0;401 for (k=0; k<a->cols; k++) {402 total+= readCell(a, i, k) * readCell(b, k, j);403 }404