=head1 NAME Catacomb::MP - Multiprecision integer arithmetic =head1 SYNOPSIS use Catacomb qw(:const :mp :random :pgen); $x = Catacomb::MP->new($str, [$radix]); $x = Catacomb::MP->new($i); $x = Catacomb::MP->loadb($bytes); $x = Catacomb::MP->loadl($bytes); $x = Catacomb::MP->loadb2c($bytes); $x = Catacomb::MP->loadl2c($bytes); ($x, $rest) = Catacomb::MP->fromstring($str, [$radix]); $x = mp($str, [$radix]); $x = mp($i); ($x, $rest) = mp_fromstring($str, [$radix]); $a = $b + $c; $a = $b - $c; $a = $b * $c; $a = $b / $c; $a = $b % $c; $a = $b ** $n; $a = $b << $n; $a = $b >> $n; $a = $b & $c; $a = $b | $c; $a = $b ^ $c; $a = ~$b; $p = $b == $c; $p = $b != $c; $p = $b < $c; $p = $b > $c; $p = $b <= $c; $p = $b >= $c; $a = sqrt($b); $a = -$b; $a = $b->add($c); $a = $b->sub($c); $a = $b->mul($c); ($q, $r) = $a->div($b); $a = $b->sqr(); $a = $b->exp($c); $a = $b->sqrt(); $a = $b->neg(); $a = $b->not(); $a = $b->not2c(); $a = $b->mod($c); $p = $b->eq($c); $cmp = $b->cmp($c); $a = $b->and($c); $a = $b->and2c($c); $a = $b->or($c); $a = $b->or2c($c); $a = $b->xor($c); $a = $b->xor2c($c); $a = $b->nand($c); $a = $b->nand2c($c); $a = $b->nor($c); $a = $b->nor2c($c); $a = $b->not(); $a = $b->not2c(); $a = $b->lsl($n); $a = $b->lsl2c($n); $a = $b->lsr($n); $a = $b->lsr2c($n); $a = $b->setbit($n); $a = $b->setbit2c($n); $a = $b->clearbit($n); $a = $b->clearbit2c($n); $p = $b->testbit($n); $p = $b->testbit2c($n); $x = $y->copy(); # largely useless $g = $a->gcd($b); ($g, $u, $v) = $a->gcd($b); ($s, $t) = $m->odd(); # m = 2^s t $a = $p->modexp($x, $e); $a = $p->modinv($b); $r = $p->modsqrt($x); $q = $n->jac($a); $p = $x->primep([$rng]); $nbits = $x->bits(); $nbytes = $x->octets(); $bytes = $x->storeb([$nbytes]); $bytes = $x->storel([$nbytes]); $bytes = $x->storeb2c([$nbytes]); $bytes = $x->storel2c([$nbytes]); $str = $x->tostring([$radix]); $n = $x->toint(); $barrett = Catacomb::MP::Barrett->new($p); $barrett = $p->barrett(); $p = $barrett->m(); $x = $barrett->reduce($y); $a = $barrett->exp($x, $y); $mont = Catacomb::MP::Mont->new($p); $mont = $p->mont(); $r = $mont->r(); $r2 = $mont->r2(); $p = $mont->m(); $x = $mont->in($y); $a = $mont->mul($x, $y); $a = $mont->expr($x, $y); $a = $mont->mexpr($x0, $e0, $x1, $e1, ...); $x = $mont->reduce($y); $x = $mont->out($y); $a = $mont->exp($x, $y); $a = $mont->mexp($x0, $e0, $x1, $e1, ...); $reduce = Catacomb::MP::Reduce->new($p); $reduce = $p->mkreduce(); $p = $reduce->m(); $x = $reduce->reduce($y); $a = $barrett->exp($x, $y); $crt = Catacomb::MP::CRT->new(@n); $n = $crt->product(); @n = $crt->moduli(); $x = $crt->solve(@r); =head1 DESCRIPTION This is a full-featured multiprecision maths library. Integer objects belong to the class C. Most standard arithmetic operators are overloaded and do the Right Thing. See below for more details. Note that multiprecision integers are I. No operation can change the value of an integer. =head2 Constructors =over =item Bnew(>iB<)> =item BIB<)> Return the multiprecision integer whose value is I. =item Bnew(>I, [I]B<)> =item BI, [I]B<)> Returns the multiprecision integer whose value is represented by I, in the given I. If I is 0, as it is by default, then I may have a prefix giving its radix: it may be B<0> for octal, B<0x> for hex, or IB<_> for radix I. If the argument is invalid, B is returned. =item Bloadb(>IB<)> =item Bloadl(>IB<)> =item BIB<)> =item BIB<)> Returns the multiprecision integer whose value is represented in big- or little-endian base-256 form by I. This will always be nonnegative. Returns the multiprecision integer whose value is represented in little-endian base-256 form by I. This will always be nonnegative. =item Bloadb2c(>IB<)> =item Bloadl2c(>IB<)> =item BIB<)> =item BIB<)> Returns the multiprecision integer whose value is represented in two's complement big- or little-endian base-256 form by I. =item Bfromstring(>I, [I]B<)> =item BI, [I]B<)> Returns the multiprecision integer whose value is represented by I, and (in a list context) the remainder of I. If I is 0 then I may have a prefix, as for B. If I is invalid, an empty list is returned. =back =head2 Methods The B package overloads the standard arithmetic operators. As long as one operand is a B object, the other may be any argument acceptable to B. As a special exception, either argument to B<*> may be a B object, to perform elliptic curve point multiplication. =over =item IB<-Eadd(>IB<)> =item IB<-Esub(>IB<)> =item IB<-Emul(>IB<)> =item IB<-Ediv(>IB<)> =item IB<-Emod(>IB<)> The basic algorithms. The argument I may be any value acceptable to the B constructor. In an array context, the B method returns a two values: the quotient and remainder. The quotient returned is the I of the true quotient: the remainder therefore has the same sign as the divisor. This is usually the right result for number-theoretic purposes. =item IB<-Esqr()> Returns the square of its argument. Usually faster than multiplying it by itself. =item IB<-Eexp(>IB<)> Returns the result I^I. Theoretically, I can be a multiprecision integer, but the result will be impossibly huge if this is the case. The exponent I may not be negative. =item IB<-Esqrt()> Returns the integer square-root of I -- i.e., the largest integer less than or equal to the true square root. =item IB<-Eeq(>IB<)> Returns true if I and I are equal; or false otherwise. =item IB<-Ecmp(>IB<)> Returns -1, 0 or +1 according to whether I is less than, equal to or greater than I. =item IB<-Eand(>IB<)> =item IB<-Eand2c(>IB<)> =item IB<-Eor(>IB<)> =item IB<-Eor2c(>IB<)> =item IB<-Exor(>IB<)> =item IB<-Exor2c(>IB<)> =item IB<-Enand(>IB<)> =item IB<-Enand2c(>IB<)> =item IB<-Enor(>IB<)> =item IB<-Enor2c(>IB<)> =item IB<-Enot()> =item IB<-Enot2c()> Standard bitwise operators. The unadorned methods ignore the sign of their operands and use only the absolute values. The B<2c> versions use a two's complement representation, with the sign bit repeated infinitely. =item IB<-Elsl(>IB<)> =item IB<-Elsl2c(>IB<)> =item IB<-Elsr(>IB<)> =item IB<-Elsr2c(>IB<)> Standard shifting operators. The unadorned methods treat only absolute values, while the B<2c> versions use a two's complement representation, with the sign bit repeated infinitely. =item IB<-Esetbit(>IB<)> =item IB<-Esetbit2c(>IB<)> =item IB<-Eclearbit(>IB<)> =item IB<-Eclearbit2c(>IB<)> Returns a copy of the argument I with bit I set or clear. The unadorned methods treat only absolute values, while the B<2c> variants use a two's complement representation with the sign bit repeated infinitely. =item IB<-Etestbit(>IB<)> =item IB<-Etestbit2c(>IB<)> Returns true or false according to whether I has bit I set or clear. The unadorned methods treat only absolute values, while the B<2c> variant uses a two's complement representation with the sign bit repeated infinitely. =item IB<-Ecopy()> Returns a copy of I. Not useful: use assignment instead. =item IB<-Egcd(>IB<)> Returns the greatest common divisor of I and I. This will never be negative. In a list context, it also returns two further results, I and I: if the GCD is I then we have I I + I I = I. Furthermore, I will have the same sign as I. =item IB<-Eodd()> Returns a pair of numbers I and I, so that I = I << I, with I odd and I as large as possible. I will be multiprecision; I will be a standard Perl integer. =item IB<-Emodexp(>IB<,> IB<)> Returns I^I mod I. =item IB<-Emodinv(>IB<)> Returns the inverse of I modulo I. If no inverse exists then report an error. =item IB<-Emodsqrt(>IB<)> If I is prime, and I is a quadratic residue mod I, then return a square root of I mod I. If I is not prime, does something arbitrary; if I is a nonresidue then report an error. =item IB<-Ejac(>IB<)> Returns the Jacobi symbol (I/I). If I is prime, then this is I^((I - 1)/2), i.e., 0 if I is a multiple of I, +1 if I is a quadratic residue modulo I, or -1 if I is a quadratic nonresidue mod I. =item IB<-Eprimep(>[I]I<)> Returns true or false, depending on whether I is (probably) prime. If I is specified, it must be a random number generator -- see Catacomb::Crypto(3). =item IB<-Ebits()> Returns the smallest number of bits required to represent the integer I. =item IB<-Eoctets()> Returns the smallest number of bytes required to represent the integer I, ignoring sign. =item IB<-Eoctets2c()> Returns the smallest number of bytes required to represent the integer I as two's complement. This may be one greater than the result returned by B in the case where the top bit of I is the top bit of an octet. =item IB<-Estoreb(>[I]B<)> =item IB<-Estorel(>[I]B<)> Return (the absolute value of) I as a raw base-256 string in big- or little-endian order. The returned string has length I, which defaults to the smallest nonzero length necessary to represent the argument. If I is too small, more significant bits are silently discarded. The sign is ignored. =item IB<-Estoreb2c(>[I]B<)> =item IB<-Estorel2c(>[I]B<)> Return I as a raw two's complement base-256 string in big- or little-endian order. The returned string has length I, which defaults to the smallest nonzero length necessary to represent the argument. If I is too small, more significant bits are silently discarded. An alternative way to look at this operation is that the returned value is congruent to I modulo 2^(8 I). =item IB<-Etostring(>[I]B<)> Return I expressed as a base-I string. The default I is 10. The result may be preceded by a minus sign if I is negative. No leading zeroes or other radix prefix are prepended. =item IB<-Etoint()> Returns I as a Perl integer. If I cannot be represented as a Perl integer then an undefined result is returned. =back =head2 Barrett reduction Barrett reduction is an efficient way of doing modular reduction on numbers which aren't too much bigger than the modulus. Barrett reduction isn't as efficient as Montgomery reduction (see below) but is simpler and works on even moduli. The precomputed information used to perform Barrett reduction are stored in an object of type B. =over =item Bnew(>IB<)> =item IB<-Ebarrett()> Create a new Barrett reduction context, set up for reducing modulo I. =item IB<-Em()> Returns the modulus stored in the reduction context I. =item IB<-Ereduce(>IB<)> Let I be the modulus stored in the reduction context I. Then, if I is nonnegative and less then I^2, returns I mod I. Otherwise the return value is undefined. =item IB<-Eexp(>IB<,> IB<)> Let I be the modulus stored in the reduction context I. Then return I^I mod I. If I is negative then I must have an inverse modulo I; otherwise you'll get a big mess. =back =head2 Montgomery reduction Montgomery reduction is a clever and efficient way of doing modular reduction on numbers which aren't too much bigger than the modulus. It only works if the modulus is positive and odd, and it's a little complicated. Let I be the modulus in question. There is a value I which is computed in some way from I. The Montgomery reduction operation, given a number I, actually returns I I^(-1) mod I, which doesn't sound useful. However, if you multiply all your numbers by a factor of I then the cleverness becomes clear: if you reduce I I I^2, you get I I I mod I. Indeed, there's an efficient multiply-and-reduce operation which takes two operands, each with a factor of I and returns a result with the factor of I. One more reduction step drops off the final factor of I to give you the real answer. Getting numbers into the required form involves multiplying by I^2 mod I and reducing: conveniently, I^2 mod I is precomputed. Addition and subtraction leave the factor of I where it was, so you can just test-and-subtract to reduce. One final tip, if you're just multiplying two numbers, multiply them together first, and then multiply the result by I^2 to fix the answer. If that all sounded too difficult, then you can use the B method to convert to internal form, B to multiply numbers in internal form, B and B to do modular exponentiation, and B to convert the result to external form. The precomputed information used to perform Montgomery reduction are stored in an object of type B. =over =item Bnew(>IB<)> =item IB<-Emont()> Constructs a Montgomery reduction context for reduction modulo I. Returns B unless I is an odd positive integer. =item IB<-Er()> Returns the Montgomery reduction factor I. =item IB<-Er2()> Returns the Montgomerization factor I^2. =item IB<-Em()> Returns the modulus I. =item IB<-Ein(>IB<)> Returns the Montgomerized form of I, i.e., I I mod I. I can be any integer. =item IB<-Emul(>IB<,> IB<)> Montgomery multiplication. If I and I are Montgomerized, then returns their Montgomerized product; i.e., I I I^(-1) mod I. =item IB<-Eexpr(>IB<,> IB<)> Montgomery exponentiation. If I is Montgomerized, then returns the Montgomerized value of I^I mod I; i.e., if I = I I, it returns I^I I mod I. Here, if I is negative, then I must have an inverse modulo I; otherwise there'll be a big mess. =item IB<-Emexpr(>IB<,> IB<,> IB<,> IB<,> ...B<)> Simultaneous Montgomery exponentiation. If the I are Montgomerized, then returns the Montgomerized value of I^I I^I ... mod I; i.e., if I = I I, it returns I^I I^I ... I mod I. Here, if some I is negative, then the corresponding I must have an inverse modulo I; otherwise there'll be a big mess. =item IB<-Ereduce(>IB<)> =item IB<-Eout(>IB<)> Returns the unMontgomerized form of I; i.e., I I^(-1) mod I. =item IB<-Eexpr(>IB<,> IB<)> Modular exponentiation. Returns I^I mod I. Here, if I is negative, then I must have an inverse modulo I; otherwise there'll be a big mess. =item IB<-Emexpr(>IB<,> IB<,> IB<,> IB<,> ...B<)> Simultaneous modular exponentiation. Returns I^I I^I ... mod I. Here, if some I is negative, then the corresponding I must have an inverse modulo I; otherwise there'll be a big mess. =back =head2 Nice prime reduction For some numbers, we can do modular reduction quite rapidly. Specifically, these are numbers of the form =over 2^I - 2^I +/- 2^I +/- ... +/- 2^I =back where I > I > ... I, for small values of I. We call such numbers `nice' (that's specific to Catacomb, not a term in general use). Usually, numbers of interest to us will be prime; hence, we shall speak of `nice primes'. Information for efficient reduction modulo a nice number is stored in an object of type B. =over =item Bnew(>IB<)> =item IB<-Emkreduce()> Create a new nice-modulus reduction context, set up for reducing modulo I. =item IB<-Em()> Returns the modulus stored in the reduction context I. =item IB<-Ereduce(>IB<)> Let I be the modulus stored in the reduction context I. Then, if I, returns I mod I. Otherwise the return value is undefined. =item IB<-Eexp(>IB<,> IB<)> Let I be the modulus stored in the reduction context I. Then return I^I mod I. If I is negative then I must have an inverse modulo I; otherwise you'll get a big mess. =back =head2 Chinese Remainder Theorem solution Catacomb can solve simultaneous congruence problems, i.e., of the form I = I (mod I) using the Chinese Remainder Theorem (CRT). It is required that the I be positive and pairwise relatively prime; otherwise you'll get an unpleasant mess. =over =item Bnew(>IB<,> IB<,> ...B<)> Construct a new CRT solving context, for solving congruences mod the I, and return it. =item IB<-Eproduct()> Returns the product of the moduli I. In a scalar context, return the number of moduli. =item IB<-Emoduli()> Returns a list of the I, as passed to B. =item IB<-Esolve(>IB<,> IB<,>, ...B<)> Returns the unique answer I (modulo the product of the I) to the congruences I = I (mod I). You will get an unhelpful answer if any I >= I, and an error if you pass the wrong number of I arguments. =back =head1 SEE ALSO Catacomb(3). =head1 AUTHOR Mark Wooding,