void multiply_bignum(bignum *a, bignum *b, bignum *c) { bignum aCopy = *a; bignum tmp; int i, j; int digit; // TODO: compare a and b for the optimized performance. if (compareBignum(a, b) < 0) { multiply_bignum(b, a, c); return; } initializeBignum(c); rightShift(&aCopy, b->numFractions); // Multiple by the fractional numbers. for (i = 0; i < b->numFractions; i++) { digit = b->integers[i]; // Add {digit} times. for (j = 1; j <= digit; j++) { addBignum(c, &aCopy, &tmp); *c = tmp; } leftShift(&aCopy, 1); } // Multiple by the integer numbers. for (i = 0; i <= b->numIntegers; i++) { digit = b->integers[i]; for(j = 1; j <= digit; j++) { addBignum(c, &aCopy, &tmp); *c = tmp; } leftShift(&aCopy, 1); } c->sign = (a->sign == b->sign) ? PLUS : MINUS; optimizeBignum(c); }
bignum::bignum(vector<int> n, int set_base, bool is_negative) { initializeBignum(); base = set_base; int count = (ONES_PLACE - 1) + n.size(); for (vector<int>::iterator i = n.begin(); i != n.end() && count >= 0; i++) { if (count >= MAXDIGITS) throw error_handler(__FILE__, __LINE__, "The value being calculated is too large for the settings provided"); if (*i >= base) throw error_handler(__FILE__, __LINE__, "One of the values passed is beyond the given base"); digits[count] = (*i); count--; } updateDigits(); negative = is_negative; }
void addBignum(bignum *a, bignum *b, bignum *c) { int carry = 0; int i = 0; int maxNumFractions = getMax(a->numFractions, b->numFractions); int maxNumDecimals = getMax(a->numIntegers, b->numIntegers); int left, right; int result; // Determine if the two numbers are both positive. If not, call the substract function. if (a->sign != b->sign) { // Call substract. if (a->sign == MINUS) { a->sign = PLUS; subtractBignum(b, a, c); a->sign = MINUS; } else { b->sign = PLUS; subtractBignum(a, b, c); b->sign = MINUS; } return; } if (a->sign == MINUS) { a->sign = b->sign = PLUS; addBignum(a, b, c); a->sign = b->sign = MINUS; c->sign = MINUS; return; } initializeBignum(c); c->numFractions = maxNumFractions; c->numIntegers = maxNumDecimals; // Adding the fractions. for (i = maxNumFractions - 1; i >= 0; i--) { left = (i <= a->numFractions - 1) ? a->fractions[i] : 0; right = (i <= b->numFractions - 1) ? b->fractions[i] : 0; result = left + right + carry; if (result >= 10) { carry = 1; result -= 10; } else { carry = 0; } c->fractions[i] = result; } // Adding the integers. for (i = 0; i < maxNumDecimals; i++) { left = (i < a->numIntegers) ? a->integers[i] : 0; right = (i < b->numIntegers) ? b->integers[i] : 0; result = left + right + carry; if (result >= 10) { carry = 1; result -= 10; } else { carry = 0; } c->integers[i] = result; } if (carry != 0) { c->integers[c->numIntegers] = 1; c->numIntegers++; } optimizeBignum(c); }
// Transfer the large number in the string to a big number. // Return 0 if succeed, 1 if fail. int stringToBignum(char* string, bignum *num) { int i; int j=0; int k = 0; int len = 0; int hasFranction = 0; char c; int charInteger = 0; int decimalsIndex = 0; int fractionIndex = 0; int numChars, numIntegers, numFractions; analizeNumString(string, &numChars, &numIntegers, &numFractions); decimalsIndex = numIntegers - 1; initializeBignum(num); num->numIntegers = 0; for (i = 0, len = numChars; i <= len; i++) { c = string[i]; if (isspace(c) || c == '\0') { break; } else if(isdigit(c)) { charInteger = c - '0'; if (hasFranction == 0) { num->integers[decimalsIndex] = charInteger; decimalsIndex--; num->numIntegers++; } else if (hasFranction == 1) { num->fractions[k] = charInteger; k++; num->numFractions++; } } else if(c == '-') { num->sign = MINUS; } else if(c == '.') { hasFranction = 1; } else { return EXIT_FAILURE; } } optimizeBignum(num); return EXIT_SUCCESS; }
bignum getZeroBignum() { bignum num; initializeBignum(&num); return num; }
int divide_bignum(bignum *a, bignum *b, bignum *c) { int aSign, bSign; /* temporary signs */ int i; /* counters */ int numShiftRequired; int answerIndex; bignum aCopy, bCopy, tempNum; int compareResult; int count = 0; int isExiting = 0; int isIntegersDone = 0; if (isBignumZero(b)) { // Divided by zero. return 0; } initializeBignum(c); if (isBignumZero(a)) { return 1; } c->sign = (a->sign == b->sign) ? PLUS : MINUS; aSign = a->sign; bSign = b->sign; a->sign = b->sign = PLUS; aCopy = *a; bCopy = *b; if (b->numIntegers == 1 && b->integers[0] == 0) { for (i = 0; i < MAX_NUM_DIGITS; i++) { if (b->fractions[i] != 0) { break; } } numShiftRequired = (a->numIntegers - b->numIntegers) + i + 1; } else { numShiftRequired = (a->numIntegers > b->numIntegers) ? a->numIntegers - b->numIntegers : 0; } c->numIntegers = numShiftRequired + 1; leftShift(&bCopy, numShiftRequired); answerIndex = numShiftRequired; // Fill up the integers. while (answerIndex >= 0) { while (1) { if (isBignumZero(&aCopy)) { isExiting = 1; break; } compareResult = compareBignum(&aCopy, &bCopy); if (compareResult < 0) { if (--answerIndex < 0) { isIntegersDone = 1; break; } leftShift(&aCopy, 1); continue; } subtractBignum(&aCopy, &bCopy, &tempNum); aCopy = tempNum; c->integers[answerIndex]++; } if (isIntegersDone || isExiting) { break; } } if (!isExiting) { answerIndex = 0; leftShift(&aCopy, 1); c->numFractions++; // Fill up the fractions. while (answerIndex < MAX_NUM_DIGITS - 1) { while (1) { if (isBignumZero(&aCopy)) { isExiting = 1; break; } compareResult = compareBignum(&aCopy, &bCopy); if (compareResult < 0) { if (++answerIndex >= MAX_NUM_DIGITS - 1) { isExiting = 1; break; } leftShift(&aCopy, 1); c->numFractions++; continue; } subtractBignum(&aCopy, &bCopy, &tempNum); aCopy = tempNum; c->fractions[answerIndex]++; } if (isExiting) { break; } } } optimizeBignum(c); a->sign = aSign; b->sign = bSign; return 1; }
bignum::bignum(float f, int decimal_places) { initializeBignum(); vector<int> exponent, mantissa; bool sign = false; //based on 32-bit system architecture static int float_bits = 32, mantissa_delim = 23, exponent_delim = 31, exponent_bias = 127; union float_converter { float f; unsigned int u; }; float_converter converter; converter.f = f; unsigned int compare = 1; //iterate through bits of the stored value, push bit value to appropriate container for (int i = 0; i < float_bits; i++) { if (i < mantissa_delim) mantissa.push_back(converter.u & compare == compare); else if (i < exponent_delim) exponent.push_back(converter.u & compare == compare); else sign = (converter.u & compare == compare); converter.u = converter.u >> 1; } //reversed to compensate for endianess std::reverse(mantissa.begin(), mantissa.end()); std::reverse(exponent.begin(), exponent.end()); //create the mantissa as a binary bignum bignum big_mantissa(mantissa, 2, false); big_mantissa.rightShift(mantissa_delim); //create the exponent as a binary bignum, adjust based on exponent bias bignum big_exponent(exponent, 2, false); bignum big_exponent_bias(exponent_bias); big_exponent_bias.convertBase(2); big_exponent -= big_exponent_bias; //generates multiplier of the floating format based on mantissa and exponent bignum mantissa_multiplier(10); mantissa_multiplier.setBase(2); mantissa_multiplier = jep::exponent(mantissa_multiplier, big_exponent); mantissa_multiplier.convertBase(2); //increment, since system architecture does not incorporate the 1 by default big_mantissa += 1; bignum temp = big_mantissa * mantissa_multiplier; if (sign) temp.setNegative(); temp.convertBase(10); *this = temp; roundToIndex(ONES_PLACE - decimal_places); }
bignum::bignum(double d, int decimal_places) { initializeBignum(); vector<int> exponent; vector<int> mantissa; bool sign = false; static int double_bits = 64, mantissa_delim = 52, exponent_delim = 63, exponent_bias = 1023; union double_converter { double d; unsigned long long int u; }; double_converter converter; converter.d = d; unsigned int compare = 1; for (int i = 0; i < double_bits; i++) { if (i < mantissa_delim) mantissa.push_back(converter.u & compare == compare); else if (i < exponent_delim) exponent.push_back(converter.u & compare == compare); else sign = (converter.u & compare == compare); converter.u = converter.u >> 1; } std::reverse(mantissa.begin(), mantissa.end()); std::reverse(exponent.begin(), exponent.end()); bignum big_mantissa(mantissa, 2, false); big_mantissa.rightShift(mantissa_delim); bignum big_exponent(exponent, 2, false); bignum big_exponent_bias(exponent_bias); big_exponent_bias.convertBase(2); big_exponent -= big_exponent_bias; //generates multiplier of the floating format bignum mantissa_multiplier(10); mantissa_multiplier.setBase(2); mantissa_multiplier = jep::exponent(mantissa_multiplier, big_exponent); mantissa_multiplier.convertBase(2); big_mantissa += 1; bignum temp = big_mantissa * mantissa_multiplier; if (sign) temp.setNegative(); temp.convertBase(10); *this = temp; roundToIndex(ONES_PLACE - decimal_places); }
bignum::bignum(string s, int baseGiven) { initializeBignum(); base = baseGiven; vector <int> numbersToAdd; int numbersAdded = 0; int decimalNumbers = 0; for (int i = 0; i < s.length(); i++) { bool decimal = false; switch (s[i]) { case ',': break; case '.': if (decimal == true) throw error_handler(__FILE__, __LINE__, "constructor failed, number contains multiple decimal points"); else decimal = true; break; case '-': if (negative == true) throw error_handler(__FILE__, __LINE__, "constructor failed, number contains multiple negative symbols"); else negative = true; break; default: char zero = '0'; char letter = 'A'; if (s[i] >= zero && s[i] <= zero + 9) { int digitToAdd = s[i] - zero; if (digitToAdd >= base) throw error_handler(__FILE__, __LINE__, "constructor failed, digit exceeds base desired"); if (decimal == true) decimalNumbers++; numbersAdded++; numbersToAdd.push_back(digitToAdd); break; } else if (s[i] >= letter && s[i] <= letter + 27) { int digitToAdd = s[i] - letter + 10; if (digitToAdd >= base) throw error_handler(__FILE__, __LINE__, "constructor failed, digit exceeds base desired"); if (decimal == true) decimalNumbers++; numbersAdded++; numbersToAdd.push_back(digitToAdd); break; } else throw error_handler(__FILE__, __LINE__, "constructor failed, invalid character(s) included"); break; } } if (decimalNumbers > ONES_PLACE) throw error_handler(__FILE__, __LINE__, "constructor failed, number has too many decimal places"); int startingPoint = ONES_PLACE + (numbersAdded - decimalNumbers) - 1; for (int i = 0; i < numbersToAdd.size(); i++) { int digitToAdd = numbersToAdd.at(i); int locationToSet = startingPoint - i; digits[locationToSet] = digitToAdd; } updateDigits(); }
bignum::bignum(string s) { initializeBignum(); vector <int> numbersToAdd; int numbersAdded = 0; int decimalNumbers = 0; bool decimal = false; int commaNumbers = 0; bool comma = false; for (int i = 0; i < s.length(); i++) { switch (s[i]) { case ',': if (decimal == true) throw error_handler(__FILE__, __LINE__, "constructor failed, comma included after decimal point"); else if (comma == true && commaNumbers != 3) throw error_handler(__FILE__, __LINE__, "constructor failed, improper use of commas"); else if (comma == false && numbersAdded > 3) throw error_handler(__FILE__, __LINE__, "constructor failed, improper use of commas"); else if (numbersAdded == 0) throw error_handler(__FILE__, __LINE__, "constructor failed, improper use of commas"); comma = true; commaNumbers = 0; break; case '.': if (decimal == true) throw error_handler(__FILE__, __LINE__, "constructor failed, number contains multiple decimal points"); else decimal = true; break; case '-': if (decimal == true) throw error_handler(__FILE__, __LINE__, "constructor failed, negative symbol included after a decimal point"); if (numbersAdded > 0) throw error_handler(__FILE__, __LINE__, "constructor failed, negative symbol included after a number"); if (comma == true) throw error_handler(__FILE__, __LINE__, "constructor failed, negative sign included after a comma"); if (negative == true) throw error_handler(__FILE__, __LINE__, "constructor failed, number contains multiple negative symbols"); else negative = true; break; default: char zero = '0'; if (s[i] >= zero && s[i] <= zero + 9) { int digitToAdd = s[i] - zero; if (digitToAdd >= base) throw error_handler(__FILE__, __LINE__, "constructor failed, digit exceeds base desired"); if (decimal == true) decimalNumbers++; if (comma == true) commaNumbers++; numbersAdded++; numbersToAdd.push_back(digitToAdd); break; } else throw error_handler(__FILE__, __LINE__, "constructor failed, invalid character(s) included"); break; } } if (decimalNumbers > ONES_PLACE) throw error_handler(__FILE__, __LINE__, "constructor failed, number has too many decimal places"); int startingPoint = ONES_PLACE + (numbersAdded - decimalNumbers) - 1; for (int i = 0; i < numbersToAdd.size(); i++) { int digitToAdd = numbersToAdd.at(i); int locationToSet = startingPoint - i; digits[locationToSet] = digitToAdd; } updateDigits(); }