void bignum_init_base_convert(size_t size, int base) { bignum multiplier; bignum_init(&multiplier); bignum_from_int(&multiplier, 1); mul_lut = malloc(size * sizeof(bignum)); mul_lut_size = size; for (int i = 0; i < size; ++i) { bignum_init(&mul_lut[i]); bignum_copy(&mul_lut[i], &multiplier); bignum_mul_int(&multiplier, base); } bignum_free(&multiplier); bignum sum; bignum_init(&sum); for (int i = 0; i < SUMSZ; ++i) { for (int j = 0; j < 256; ++j) { int m = i*8; bignum_from_int(&sum, 0); for (uint8_t mask = 1; mask != 0; mask <<= 1) { if (j & mask) { bignum_add(&sum, &mul_lut[m]); } ++m; } bignum_init(&sum_lut[i][j]); bignum_copy(&sum_lut[i][j], &sum); } } bignum_free(&sum); }
/** * NAME: regular_mult * INPUT: MATRIX* m1, MATRIX* m2, MATRIX* res * USAGE: Multiplies m1 and m2 naively and stores the result in res. * * NOTES: pointers for m1, m2, m3 must all be malloced before using this function. */ void regular_mult(MATRIX* m1, MATRIX* m2, MATRIX* res) { // Checks to see whether m1 and m2 can be multiplied. if (m1->numCols != m2->numRows) { printf("Error: Matrices cannot be multiplied"); return; } // Define numRows and numCols of res int rowSize = m1->numRows; int colSize = m2->numCols; // Fill in matrix information res->numRows = rowSize; res->numCols = colSize; // Allocate memory for the rows of the matrix. res->matrix = (BIGNUM**) malloc(rowSize * sizeof(BIGNUM*)); for(int i = 0; i < rowSize; i++) { // Allocate memory for each entry in the matrix. res->matrix[i] = (BIGNUM*) malloc(colSize * sizeof(BIGNUM)); // Go across the columns of m2 for (int j=0; j< colSize; j++) { // Initialize a temporary bignum to store a sum. BIGNUM* sum = malloc(sizeof(BIGNUM)); bignum_from_int(0,sum); // Go down the rows of m1 and across the columns of m2. // Naive multiplication is performed here. for (int k = 0; k < m1->numCols; k++) { // Initialize a temporary bignum to store the result of multiplication. BIGNUM* multRes = malloc(sizeof(BIGNUM)); bignum_from_int(0,multRes); mult_bignums(&m1->matrix[i][k], &m2->matrix[k][j], multRes); // Initialize a temporary bignum for addition. BIGNUM* addRes = malloc(sizeof(BIGNUM)); bignum_from_int(0,addRes); add_bignums(multRes, sum, addRes); // Store the addition and free varibles. *sum = *addRes; free(multRes); free(addRes); } // Store the sum into the matrix and free temp bignum. res->matrix[i][j] = *sum; free(sum); } } }
/* Examples: 82000 (base 3) = 11011111001 = 1*3**0 + 0*3**1 + 0*3**2 + 1*3**3 +3**4 +3**5 +3**6 +3**7 +0*3**8 +3**9 +3**10 82000 (base 5) = 10111000 = 0*5**0 + 0*5**1 + 0*5**2 + 1*5**3 + 1*5**4 + 1*5**5 + 0*5**6 + 1*5**7 */ void bignum_from_string_binary(bignum *n, char const* s, size_t base) { char const *end_of_s = s + strlen(s) - 1; bignum_from_int(n, 0); bignum multiplier; bignum_init(&multiplier); bignum_from_int(&multiplier, 1); while (end_of_s != s) { assert((*end_of_s == '1') || (*end_of_s == '0')); if (*end_of_s == '1') { bignum_add(n, &multiplier); } bignum_mul_int(&multiplier, base); --end_of_s; } bignum_add(n, &multiplier); bignum_free(&multiplier); }
// remainder is optional void bignum_div_mod(bignum *a, bignum *b, bignum *remainder) { int i = a->size; unsigned int temp = 0; int bb = bignum_to_int(b); while (i > 0) { --i; temp <<= 8; temp |= a->data[i]; a->data[i] = temp / bb; temp -= a->data[i] * bb; } if (remainder) { bignum_from_int(remainder, temp); } while (a->size > 0 && a->data[a->size - 1] == 0) { --a->size; } if (a->size == 0) { a->size = 1; } }
// assign n from s, treat s as being in base 'base' void bignum_base_convert(bignum *n, bignum* s) { bignum_from_int(n, 0); for (int i = 0; i < s->size; ++i) { bignum_add(n, &sum_lut[i][s->data[i]]); } }