bigInt myPow(bigInt base, bigInt exp) { // возведение base в степень exp // такое имя потому, что есть стандартная функция с таким же именем, // а в си плоховато с перегрузкой функций bigInt res = createFromInt(1); // сюда будет записан результат bigInt zero = createFromInt(0); bigInt i = copy(exp); // сколько раз результат необходимо умножить на exp bigInt minusOne = createFromInt(-1); // -1 // пока количество необходимых умножений больше нуля while (compare(i, zero) > 0) { // res = res * base bigInt tmp = mul(res, base); free(res.digits); res = tmp; // смысл следующих трёх строчек: i = i -1 tmp = sumAndSub(i, minusOne); // складываем i и (-1), т.е. tmp = i - 1 free(i.digits); // очищаем память i = tmp; } // очищаем память free(i.digits); free(zero.digits); free(minusOne.digits); return res; }
bigInt powMod(bigInt base, bigInt exp, bigInt modul) { // возведение base в степень exp по модулю modul // используется алгоритм быстрого возведения в степень bigInt res = createFromInt(1); // сюда будет записан результат bigInt zero = createFromInt(0); bigInt two = createFromInt(2); bigInt b = copy(exp); bigInt a = copy(base); while (compare(b, zero) > 0) { if (odd(b)) { // res = (res * a) % modul; // tmp = res * base bigInt tmp = mul(res, a); // res = tmp % modul bigInt modRem; // сюда запишем остаток от деления bigInt tmp2 = dividing(tmp, modul, &modRem); free(tmp2.digits); free(tmp.digits); free(res.digits); res = modRem; } // a = (a*a) % modul bigInt tmp = mul(a, a); free(a.digits); bigInt modRem; // сюда запишем остаток от деления bigInt tmp2 = dividing(tmp, modul, &modRem); free(tmp2.digits); free(tmp.digits); a = modRem; // b = b /2 tmp = dividing(b, two, &modRem); free(b.digits); free(modRem.digits); b = tmp; } // очищаем память free(b.digits); free(zero.digits); free(two.digits); return res; }
int saveTobinarFile(const char* filename, bigInt A) { // будем считать, что в бинарный файл необходимо записать число по основанию 256 // то есть необходимо перейти от BASE к 256 (256 - потому что максимальное значение байта - 255) // для этого надо находить остатки от деления на 256 // пока число не уменьшиться до 0 // возвращаем 0 в случае успешной записи // не 0 - в случае ошибки FILE* pfDestination = fopen(filename, "w+b"); if (!pfDestination) return 1; struct bigInt tmp = copy(A); // число, которое будем делить на 256 tmp.sign = 0; // не будем обращать внимания на знак bigInt zero = createFromInt(0); bigInt b256 = createFromInt(256); // пока число не станет равным 0 while (compare(tmp, zero) != 0) { bigInt ost; // куда будет записан остаток от деления на 256 // tmp = tmp / 256 bigInt tmp2 = dividing(tmp, b256, &ost); free(tmp.digits); tmp = tmp2; // теперь в ost очередной остаток от деления на 256 // запишем его в файл fwrite((char*)&ost.digits[0], sizeof(unsigned char), 1, pfDestination); free(ost.digits); } free(tmp.digits); free(b256.digits); free(zero.digits); fclose(pfDestination); return 0; }
KernelVariable::uniquePtr KernelVariable::createFromVec2i(const std::string& varName, const Vec2i& vec) { return createFromInt(varName, (int*)&vec, 2); }
bigInt getFrombinarFile(const char* filename) { // будем считать, что в бинарном файле записаны разряды числа по модулю 256. // таким образом, чтобы считать число из бинарного файла необходимо каждый байт // умножить на 256 ^ i, где i - позиция байта в файле и всё это сложить FILE* pfSource = fopen(filename, "r+b"); if (!pfSource) { // если файл не открылся bigInt res; res.sizeNum = 0; res.sign = 0; res.digits = NULL; return res; } // узнаем размер файла fseek(pfSource, 0, SEEK_END); int filesizeNum = ftell(pfSource); fseek(pfSource, 0, SEEK_SET); // считываем содержимое файла unsigned char* fileContent = (unsigned char*)malloc(filesizeNum); fread((char*) fileContent, sizeof(unsigned char), filesizeNum, pfSource); fclose(pfSource); bigInt pow256 = createFromInt(1); // здесь будет 256 ^ i bigInt res = createFromInt(0); // здесь сформируем результат bigInt b256 = createFromInt(256); // число 256 // цикл для всех байтов в файле int i; for (i = 0; i < filesizeNum; i++) { bigInt fi = createFromInt(fileContent[i]); // получили очередной байт файла // res = res + pow256 * fi; // tmp = fi * 256 ^ i bigInt tmp = mul(fi, pow256); free(fi.digits); // tmp2 = res + tmp = res + fi * 256^i bigInt tmp2 = sumAndSub(res, tmp); free(tmp.digits); free(res.digits); res = tmp2; // res = res + pow256 * fi; // pow256 = pow256*256 tmp = mul(pow256, b256); free(pow256.digits); pow256 = tmp; } free(fileContent); free(pow256.digits); free(b256.digits); return res; }
bigInt dividing(bigInt A, bigInt B, bigInt* ost) { *ost = copy(A); ost->sign = 0; bigInt divider = copy(B); divider.sign = 0; if (1 == divider.sizeNum) { if (divider.digits[0] == 0) { ost->sizeNum = 0; ost->sign = 0; ost->digits = NULL; bigInt a; a.sizeNum = 0; a.sign = 0; a.digits = NULL; free(divider.digits); return a; } } if (compare(*ost, divider) < 0) { ost->sign = A.sign; bigInt res; res.sign = 0; res.sizeNum = 1; res.digits = (unsigned int*)malloc((res.sizeNum)*sizeof(unsigned int)); res.digits[0] = 0; free(divider.digits); return res; } if (divider.sizeNum == 1) { bigInt res; res.sizeNum = A.sizeNum; res.digits = (unsigned int*)malloc((res.sizeNum)*sizeof(unsigned int)); unsigned long long int carry = 0; int i; for (i = A.sizeNum - 1; i >= 0; i--) { unsigned long long int temp = carry; temp *= BASE; temp += A.digits[i]; res.digits[i] = temp / divider.digits[0]; carry = (unsigned long long int) temp - (unsigned long long int) res.digits[i] * (unsigned long long int) divider.digits[0]; } ost->sign = (A.sign != B.sign); if (ost->sizeNum > 0) free(ost->digits); ost->sizeNum = 1; ost->digits = (unsigned int*)malloc((1)*sizeof(unsigned int)); ost->digits[0] = carry; *ost = DelZeros(*ost); res.sign = (A.sign != B.sign); res = DelZeros(res); free(divider.digits); return res; } bigInt res; res.sign = 0; res.sizeNum = A.sizeNum - B.sizeNum + 1; res.digits = (unsigned int*)malloc((res.sizeNum)*sizeof(unsigned int)); int i; for (i = A.sizeNum - B.sizeNum + 1; i != 0; i--) { long long int qGuessMax = BASE; // для того, чтобы qGuessMin могло быть равно BASE - 1 long long int qGuessMin = 0; long long int qGuess = qGuessMax; while (qGuessMax - qGuessMin > 1) { qGuess = (qGuessMax + qGuessMin) / 2; bigInt qGuesslargeNum = createFromInt(qGuess); bigInt tmp = mul(divider, qGuesslargeNum); free(qGuesslargeNum.digits); tmp = shiftLeft(tmp, i - 1); if (compare(tmp, *ost) > 0) qGuessMax = qGuess; else qGuessMin = qGuess; free(tmp.digits); } bigInt qGuessMinlargeNum = createFromInt(qGuessMin); bigInt tmp = mul(divider, qGuessMinlargeNum); free(qGuessMinlargeNum.digits); tmp = shiftLeft(tmp, i - 1); bigInt tmpRem = copy(*ost); bigInt minusTmp = minus(tmp); free(ost->digits); *ost = sumAndSub(tmpRem, minusTmp); free(tmpRem.digits); free(minusTmp.digits); free(tmp.digits); res.digits[i - 1] = qGuessMin; } res.sign = (A.sign != B.sign); ost->sign = (A.sign != B.sign); *ost = DelZeros(*ost); res = DelZeros(res); free(divider.digits); return res; }