Modular exponentiation overflows when using multiple of two uint_32 numbers - c++

I am trying to implement RSA key signing and verifying.
I am making use of the modular exponentiation where I am encountering errors possibly due to integer overflow.
uint64_t modmult(uint64_t a,uint64_t b,uint64_t mod)
{
if (a == 0 || b < mod / a)
return ((uint64_t)a*b)%mod;
uint64_t sum;
sum = 0;
while(b>0)
{
if(b&1)
sum = (sum + a) % mod;
a = (2*a) % mod;
b>>=1;
}
return sum;
}
uint64_t modpow( uint64_t a,uint64_t b,uint64_t mod)
{
uint64_t product,pseq;
product=1;
pseq=a%mod;
while(b>0)
{
if(b&1)
product=modmult(product,pseq,mod);
pseq=modmult(pseq,pseq,mod);
b>>=1;
}
return product;
}
The function call
long long d = 2897297195663230443;
uint64_t n = 10136926879504331723;
modpow(1233,d,n);
The n is a multiple of two unsigned uint32_t prime numbers (4063800743,2494444861) the modular exponentiation
the result is 3148683887780272464, but it should be 9640529604970470922
Basically, this implementation is not handling unsigned 64 integer values of n well

The problem is that, due to the modulus being > 263, the a + sum step in your modmult routine might overflow, losing a bit. The same might happen with 2*a.
One way to fix the problem would be to add a modadd routine:
uint64_t modadd(uint_64_t a, uint64_t b, uint64_t mod) {
if (a >= mod) a %= mod; // precondition -- might not be needed if the caller can guarentee it.
if (b >= mod) b %= mod; // precondition -- might not be needed if the caller can guarentee it
a += b;
if (a >= mod || a < b) a -= mod;
return a;
}
Then, use modadd(sum, a, mod) and modadd(a, a, mod) in your modmult routine.

Related

Issue with Modular Exponentiation C++

I'm trying to perform Modular Exponentiation for large values (upto 64-bits) and I wrote this function for it:
uint64_t modularExp(uint64_t num, uint64_t exp, uint64_t mod)
{
string expBits = bitset<64>(exp).to_string();
expBits = expBits.substr(expBits.find("1")+1);
string operations = "";
uint64_t result = num;
for (int i = 0; i < expBits.length(); ++i)
{
result = (uint64_t)pow(result, 2) % mod;
if (expBits[i] == '1')
result = (result * num) % mod;
}
return result;
}
This works good with small numbers (8 digits or less) but for large numbers, even though they're in the 64 bit range, the result comes out wrong.
Additionally, when the value of mod exceeds 4294967296 (Max 32 bit value), the result just comes out as zero. I suspect the pow function perhaps has a role to play in this issue but I can't figure it out for sure.
Any advice would be greatly appreciated.
First of all, some general advice:
It's better not to use strings when working with integers, as operations with strings are much slower and might become a bottleneck for performance. It's also less clear what is actually being done when strings are involved.
You shouldn't use std::pow with integers, because it operates on floating-point numbers and loses precision.
For the main question, as a workaround, you can use this O(log^2(n)) solution, which should work for arguments up to 63 bits (since it only ever uses addition and multiplication by 2). Note how all that string magic is unnecessary if you just iterate over the bits in small-to-large order:
#include <cstdint>
uint64_t modular_mul(uint64_t a, uint64_t b, uint64_t mod) {
uint64_t result = 0;
for (uint64_t current_term = a; b; b >>= 1) {
if (b & 1) {
result = (result + current_term) % mod;
}
current_term = 2 * current_term % mod;
}
return result;
}
uint64_t modular_pow(uint64_t base, uint64_t exp, uint64_t mod) {
uint64_t result = 1;
for (uint64_t current_factor = base; exp; exp >>= 1) {
if (exp & 1) {
result = modular_mul(result, current_factor, mod);
}
current_factor = modular_mul(current_factor, current_factor, mod);
}
return result;
}
Also, in gcc a (non-standard) __uint128_t is available for some targets. (which can be used to replace modular_mul with normal multiplication)

miller-rabin test don't work for 252097800623

I'm trying to write miller-rabin test. I found few codes such as:
https://www.sanfoundry.com/cpp-program-implement-miller-rabin-primality-test/
https://www.geeksforgeeks.org/primality-test-set-3-miller-rabin/
Of course all this codes works for 252097800623 ( which is prime number ), but this is becaouse they are parsing it to int. When I changed all ints to long long in this codes they are now returning NO. I also wrote my own code based on another article and it worked when I was testing it with small numbers like 11, 101, 17 and even 1000000007, but chrashed on greater numbers like 252097800623. I want to write program that works for all integers from 1 to 10^18
EDIT
here is modified code form 1st link:
/*
* C++ Program to Implement Milong longer Rabin Primality Test
*/
#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;
/*
* calculates (a * b) % c taking long longo account that a * b might overflow
*/
long long mulmod(long long a, long long b, long long mod)
{
long long x = 0,y = a % mod;
while (b > 0)
{
if (b % 2 == 1)
{
x = (x + y) % mod;
}
y = (y * 2) % mod;
b /= 2;
}
return x % mod;
}
/*
* modular exponentiation
*/
long long modulo(long long base, long long exponent, long long mod)
{
long long x = 1;
long long y = base;
while (exponent > 0)
{
if (exponent % 2 == 1)
x = (x * y) % mod;
y = (y * y) % mod;
exponent = exponent / 2;
}
return x % mod;
}
/*
* Milong longer-Rabin primality test, iteration signifies the accuracy
*/
bool Miller(long long p,long long iteration)
{
if (p < 2)
{
return false;
}
if (p != 2 && p % 2==0)
{
return false;
}
long long s = p - 1;
while (s % 2 == 0)
{
s /= 2;
}
for (long long i = 0; i < iteration; i++)
{
long long a = rand() % (p - 1) + 1, temp = s;
long long mod = modulo(a, temp, p);
while (temp != p - 1 && mod != 1 && mod != p - 1)
{
mod = mulmod(mod, mod, p);
temp *= 2;
}
if (mod != p - 1 && temp % 2 == 0)
{
return false;
}
}
return true;
}
//Main
int main()
{
long long iteration = 5;
long long num;
cout<<"Enter long longeger to test primality: ";
cin>>num;
if (Miller(num, iteration))
cout<<num<<" is prime"<<endl;
else
cout<<num<<" is not prime"<<endl;
return 0;
}
The code in the first link, which you replicated in your question, replacing the (bad) macro ll with long long (although this produces exactly the same preprocessed code) and all int with long long, is already broken for large values, see compiler explorer here. I forced the compiler to evaluate the Miller function for 252097800623 at compile time, replacing the call to rand() with one random number 123456.
As you can see the compiler is telling me that it cannot do so, because there are integer overflows in the program. In particular:
<source>:133:17: error: static_assert expression is not an integral constant expression
static_assert(Miller(num, iteration));
^~~~~~~~~~~~~~~~~~~~~~
<source>:62:12: note: value 232307310937188460801 is outside the range of representable values of type 'long long'
y = (y * y) % mod;
^
<source>:104:14: note: in call to 'modulo(123457, 63024450155, 252097800623)'
ll mod = modulo(a, temp, p);
^
<source>:133:17: note: in call to 'Miller(252097800623, 5)'
static_assert(Miller(num, iteration));
As you can see long long is simply too small to handle inputs that large to this algorithm.

Rounding integer division without logical operators

I want a function
int rounded_division(const int a, const int b) {
return round(1.0 * a/b);
}
So we have, for example,
rounded_division(3, 2) // = 2
rounded_division(2, 2) // = 1
rounded_division(1, 2) // = 1
rounded_division(0, 2) // = 0
rounded_division(-1, 2) // = -1
rounded_division(-2, 2) // = -1
rounded_division(-3, -2) // = 2
Or in code, where a and b are 32 bit signed integers:
int rounded_division(const int a, const int b) {
return ((a < 0) ^ (b < 0)) ? ((a - b / 2) / b) : ((a + b / 2) / b);
}
And here comes the tricky part: How to implement this guy efficiently (not using larger 64 bit values) and without a logical operators such as ?:, &&, ...? Is it possible at all?
The reason why I am wondering of avoiding logical operators, because the processor I have to implement this function for, has no conditional instructions (more about missing conditional instructions on ARM.).
a/b + a%b/(b/2 + b%2) works quite well - not failed in billion+ test cases. It meets all OP's goals: No overflow, no long long, no branching, works over entire range of int when a/b is defined.
No 32-bit dependency. If using C99 or later, no implementation behavior restrictions.
int rounded_division(int a, int b) {
int q = a / b;
int r = a % b;
return q + r/(b/2 + b%2);
}
This works with 2's complement, 1s' complement and sign-magnitude as all operations are math ones.
How about this:
int rounded_division(const int a, const int b) {
return (a + b/2 + b * ((a^b) >> 31))/b;
}
(a ^ b) >> 31 should evaluate to -1 if a and b have different signs and 0 otherwise, assuming int has 32 bits and the leftmost is the sign bit.
EDIT
As pointed out by #chux in his comments this method is wrong due to integer division. This new version evaluates the same as OP's example, but contains a bit more operations.
int rounded_division(const int a, const int b) {
return (a + b * (1 + 2 * ((a^b) >> 31)) / 2)/b;
}
This version still however does not take into account the overflow problem.
What about
...
return ((a + (a*b)/abs(a*b) * b / 2) / b);
}
Without overflow:
...
return ((a + ((a/abs(a))*(b/abs(b))) * b / 2) / b);
}
This is a rough approach that you may use. Using a mask to apply something if the operation a*b < 0.
Please note that I did not test this appropriately.
int function(int a, int b){
int tmp = float(a)/b + 0.5;
int mask = (a*b) >> 31; // shift sign bit to set rest of the bits
return tmp - (1 & mask);//minus one if a*b was < 0
}
The following rounded_division_test1() meets OP's requirement of no branching - if one counts sign(int a), nabs(int a), and cmp_le(int a, int b) as non-branching. See here for ideas of how to do sign() without compare operators. These helper functions could be rolled into rounded_division_test1() without explicit calls.
The code demonstrates the correct functionality and is useful for testing various answers. When a/b is defined, this answer does not overflow.
#include <limits.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
int nabs(int a) {
return (a < 0) * a - (a >= 0) * a;
}
int sign(int a) {
return (a > 0) - (a < 0);
}
int cmp_le(int a, int b) {
return (a <= b);
}
int rounded_division_test1(int a, int b) {
int q = a / b;
int r = a % b;
int flag = cmp_le(nabs(r), (nabs(b) / 2 + nabs(b % 2)));
return q + flag * sign(b) * sign(r);
}
// Alternative that uses long long
int rounded_division_test1LL(int a, int b) {
int c = (a^b)>>31;
return (a + (c*2 + 1)*1LL*b/2)/b;
}
// Reference code
int rounded_division(int a, int b) {
return round(1.0*a/b);
}
int test(int a, int b) {
int q0 = rounded_division(a, b);
//int q1 = function(a,b);
int q1 = rounded_division_test1(a, b);
if (q0 != q1) {
printf("%d %d --> %d %d\n", a, b, q0, q1);
fflush(stdout);
}
return q0 != q1;
}
void tests(void) {
int err = 0;
int const a[] = { INT_MIN, INT_MIN + 1, INT_MIN + 1, -3, -2, -1, 0, 1, 2, 3,
INT_MAX - 1, INT_MAX };
for (unsigned i = 0; i < sizeof a / sizeof a[0]; i++) {
for (unsigned j = 0; j < sizeof a / sizeof a[0]; j++) {
if (a[j] == 0) continue;
if (a[i] == INT_MIN && a[j] == -1) continue;
err += test(a[i], a[j]);
}
}
printf("Err %d\n", err);
}
int main(void) {
tests();
return 0;
}
Let me give my contribution:
What about:
int rounded_division(const int a, const int b) {
return a/b + (2*(a%b))/b;
}
No branch, no logical operators, only mathematical operators. But it could fail if b is great than INT_MAX/2 or less than INT_MIN/2.
But if 64 bits are allowed to compute 32 bits rounds. It will not fail
int rounded_division(const int a, const int b) {
return a/b + (2LL*(a%b))/b;
}
Code that I came up with for use on ARM M0 (no floating point, slow divide).
It only uses one divide instruction and no conditionals, but will overflow if numerator + (denominator/2) > INT_MAX.
Cycle count on ARM M0 = 7 cycles + the divide (M0 has no divide instruction, so it is toolchain dependant).
int32_t Int32_SignOf(int32_t val)
{
return (+1 | (val >> 31)); // if v < 0 then -1, else +1
}
uint32_t Int32_Abs(int32_t val)
{
int32_t tmp = val ^ (val >> 31);
return (tmp - (val >> 31));
// the following code looks like it should be faster, using subexpression elimination
// except on arm a bitshift is free when performed with another operation,
// so it would actually end up being slower
// tmp = val >> 31;
// dst = val ^ (tmp);
// dst -= tmp;
// return dst;
}
int32_t Int32_DivRound(int32_t numerator, int32_t denominator)
{
// use the absolute (unsigned) demominator in the fudge value
// as the divide by 2 then becomes a bitshift
int32_t sign_num = Int32_SignOf(numerator);
uint32_t abs_denom = Int32_Abs(denominator);
return (numerator + sign_num * ((int32_t)(abs_denom / 2u))) / denominator;
}
since the function seems to be symmetric how about sign(a/b)*floor(abs(a/b)+0.5)

How to calculate EXTREMELY big binomial coefficients modulo by prime number?

This problem's answer turns out to be calculating large binomial coefficients modulo prime number using Lucas' theorem. Here's the solution to that problem using this technique: here.
Now my questions are:
Seems like my code expires if the data increases due to overflow of variables. Any ways to handle this?
Are there any ways to do this without using this theorem?
EDIT: note that as this is an OI or ACM problem, external libs other than original ones are not permitted.
Code below:
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
#define N 100010
long long mod_pow(int a,int n,int p)
{
long long ret=1;
long long A=a;
while(n)
{
if (n & 1)
ret=(ret*A)%p;
A=(A*A)%p;
n>>=1;
}
return ret;
}
long long factorial[N];
void init(long long p)
{
factorial[0] = 1;
for(int i = 1;i <= p;i++)
factorial[i] = factorial[i-1]*i%p;
//for(int i = 0;i < p;i++)
//ni[i] = mod_pow(factorial[i],p-2,p);
}
long long Lucas(long long a,long long k,long long p)
{
long long re = 1;
while(a && k)
{
long long aa = a%p;long long bb = k%p;
if(aa < bb) return 0;
re = re*factorial[aa]*mod_pow(factorial[bb]*factorial[aa-bb]%p,p-2,p)%p;
a /= p;
k /= p;
}
return re;
}
int main()
{
int t;
cin >> t;
while(t--)
{
long long n,m,p;
cin >> n >> m >> p;
init(p);
cout << Lucas(n+m,m,p) << "\n";
}
return 0;
}
This solution assumes that p2 fits into an unsigned long long. Since an unsigned long long has at least 64 bits as per standard, this works at least for p up to 4 billion, much more than the question specifies.
typedef unsigned long long num;
/* x such that a*x = 1 mod p */
num modinv(num a, num p)
{
/* implement this one on your own */
/* you can use the extended Euclidean algorithm */
}
/* n chose m mod p */
/* computed with the theorem of Lucas */
num modbinom(num n, num m, num p)
{
num i, result, divisor, n_, m_;
if (m == 0)
return 1;
/* check for the likely case that the result is zero */
if (n < m)
return 0;
for (n_ = n, m_ = m; m_ > 0; n_ /= p, m_ /= p)
if (n_ % p < m_ % p)
return 0;
for (result = 1; n >= p || m >= p; n /= p, m /= p) {
result *= modbinom(n % p, m % p, p);
result %= p;
}
/* avoid unnecessary computations */
if (m > n - m)
m = n - m;
divisor = 1;
for (i = 0; i < m; i++) {
result *= n - i;
result %= p;
divisor *= i + 1;
divisor %= p;
}
result *= modinv(divisor, p);
result %= p;
return result;
}
An infinite precision integer seems like the way to go.
If you are in C++,
the PicklingTools library has an "infinite precision" integer (similar to
Python's LONG type). Someone else suggested Python, that's a reasonable
answer if you know Python. if you want to do it in C++, you can
use the int_n type:
#include "ocval.h"
int_n n="012345678910227836478627843";
n = n + 1; // Can combine with other plain ints as well
Take a look at the documentation at:
http://www.picklingtools.com/html/usersguide.html#c-int-n-and-the-python-arbitrary-size-ints-long
and
http://www.picklingtools.com/html/faq.html#c-and-otab-tup-int-un-int-n-new-in-picklingtools-1-2-0
The download for the C++ PicklingTools is here.
You want a bignum (a.k.a. arbitrary precision arithmetic) library.
First, don't write your own bignum (or bigint) library, because efficient algorithms (more efficient than the naive ones you learned at school) are difficult to design and implement.
Then, I would recommend GMPlib. It is free software, well documented, often used, quite efficient, and well designed (with perhaps some imperfections, in particular the inability to plugin your own memory allocator in replacement of the system malloc; but you probably don't care, unless you want to catch the rare out-of-memory condition ...). It has an easy C++ interface. It is packaged in most Linux distributions.
If it is a homework assignment, perhaps your teacher is expecting you to think more on the math, and find, with some proof, a way of solving the problem without any bignums.
Lets suppose that we need to compute a value of (a / b) mod p where p is a prime number. Since p is prime then every number b has an inverse mod p. So (a / b) mod p = (a mod p) * (b mod p)^-1. We can use euclidean algorithm to compute the inverse.
To get (n over k) we need to compute n! mod p, (k!)^-1, ((n - k)!)^-1. Total time complexity is O(n).
UPDATE: Here is the code in c++. I didn't test it extensively though.
int64_t fastPow(int64_t a, int64_t exp, int64_t mod)
{
int64_t res = 1;
while (exp)
{
if (exp % 2 == 1)
{
res *= a;
res %= mod;
}
a *= a;
a %= mod;
exp >>= 1;
}
return res;
}
// This inverse works only for primes p, it uses Fermat's little theorem
int64_t inverse(int64_t a, int64_t p)
{
assert(p >= 2);
return fastPow(a, p - 2, p);
}
int64_t binomial(int64_t n, int64_t k, int64_t p)
{
std::vector<int64_t> fact(n + 1);
fact[0] = 1;
for (auto i = 1; i <= n; ++i)
fact[i] = (fact[i - 1] * i) % p;
return ((((fact[n] * inverse(fact[k], p)) % p) * inverse(fact[n - k], p)) % p);
}

return very large integer from recursive function

I have made a recursive function in c++ which deals with very large integers.
long long int findfirst(int level)
{
if(level==1)
return 1;
else if(level%2==0)
return (2*findfirst(--level));
else
return (2*findfirst(--level)-1);
}
when the input variable(level) is high,it reaches the limit of long long int and gives me wrong output.
i want to print (output%mod) where mod is 10^9+7(^ is power) .
int main()
{
long long int first = findfirst(143)%1000000007;
cout << first;
}
It prints -194114669 .
Normally online judges problem don't require the use of large integers (normally meaning almost always), if your solution need large integers probably is not the best solution to solve the problem.
Some notes about modular arithmetic
if a1 = b1 mod n and a2 = b2 mod n then:
a1 + a2 = b1 + b2 mod n
a1 - a2 = b1 - b2 mod n
a1 * a2 = b1 * b2 mod n
That mean that modular arithmetic is transitive (a + b * c) mod n could be calculated as (((b mod n) * (c mod n)) mod n + (a mod n)) mod n, I know there a lot of parenthesis and sub-expression but that is to avoid integer overflow as much as we can.
As long as I understand your program you don't need recursion at all:
#include <iostream>
using namespace std;
const long long int mod_value = 1000000007;
long long int findfirst(int level) {
long long int res = 1;
for (int lev = 1; lev <= level; lev++) {
if (lev % 2 == 0)
res = (2*res) % mod_value;
else
res = (2*res - 1) % mod_value;
}
return res;
}
int main() {
for (int i = 1; i < 143; i++) {
cout << findfirst(i) << endl;
}
return 0;
}
If you need to do recursion modify you solution to:
long long int findfirst(int level) {
if (level == 1)
return 1;
else if (level % 2 == 0)
return (2 * findfirst(--level)) % mod_value;
else
return (2 * findfirst(--level) - 1) % mod_value;
}
Where mod_value is the same as before:
Please make a good study of modular arithmetic and apply in the following online challenge (the reward of discovery the solution yourself is to high to let it go). Most of the online challenge has a mathematical background.
If the problem is (as you say) it overflows long long int, then use an arbitrary precision Integer library. Examples are here.