NAME
Math::ModInt - modular integer arithmetic
VERSION
This documentation refers to version 0.001 of Math::ModInt.
SYNOPSIS
use Math::ModInt qw(mod);
$a = mod(32, 127); # 32 (mod 127)
$b = $a->new(99); # 99 (mod 127)
$c = $a + $b; # 4 (mod 127)
$d = $a**2 - $b/$a; # 120 (mod 127)
$m = $d->modulus; # 127
$r = $d->residue; # 120
$s = $d->signed_residue; # -7
$t = "$a"; # 'mod(32, 127)'
DESCRIPTION
Math::ModInt provides overloaded operators for modular integer arithmetic. Math::ModInt objects represent integer residue classes. These objects can be used in arithmetic expressions just like Perl numbers. Math::ModInt objects are immutable. Mutators like +=
will replace an object rather than change its state.
In mixed expressions with Math::ModInt objects and ordinary numbers the numbers are interpreted as their residue class modulo the modulus of the rest of the expression. Different moduli must not be mixed, though.
There are different implementations, optimized for moduli of a particular size or using a particular math library. The base module will transparently choose a suitable back-end whenever a constructor is called.
Application Interface
Constructors
- new
-
Called as a class method,
Math::ModInt->new($residue, $modulus)
creates a new object of a subclass appropriate for the given modulus and current platform. The modulus must be a positive integer value.Called as an object method,
$x->new($residue)
creates a new object sharing both its type and modulus with the invocant object$x
. - mod
-
For convenience,
mod
can be imported as an abbreviation for the class method constructor;mod($residue, $modulus)
is equivalent toMath::ModInt->new($residue, $modulus)
. Note thatmod
has to be called as a plain function, not like a method. - undefined
-
This method returns the
undefined
placeholder object representing undefined results in the domain of modular integer arithmetic, such as from division by an operand not coprime to the modulus. See Math::ModInt::Event for how to control whether this object or other ways to report arithmetic faults should be employed.
Operators
+ - * / ** == !=
-
Addition, negation, subtraction, multiplication, division, exponentiation with integer exponents, and equivalence operators are provided through overloaded perl operators. Division or exponentiation with negative exponents may trigger an
UndefinedResult
event and yield anundefined
result.Operands must either have the same modulus or be plain integers, except for equality/inequality checks. Operands with different moduli may be compared and are considered unequal.
For other exceptions to the requirement of identical moduli, see Math::ModInt::ChineseRemainder.
Note that neither the modulo operator
%
nor bit-operations& | ^ << >>
nor order relations< <= > >= <=>
are defined. - inverse
-
The object method
$x->inverse
returns the multiplicative modular inverse of$x
, if it exists, otherwise theundefined
placeholder. (y is the modular inverse of x modulo m if x * y is equivalent to 1 modulo m.)
Accessors
- is_defined
- is_undefined
-
The object methods
$x->is_defined
and$x->is_undefined
return boolean values checking whether$x
is a proper residue class object or theundefined
placeholder. Besidesas_string
, these are the only legal accessors for theundefined
placeholder. - modulus
-
The object method
$x->modulus
returns the modulus of the residue class the object represents. - residue
-
The object method
$x->residue
returns the normalized residue of the residue class the object represents. Its value is chosen as if it was a division remainder, i.e. between zero (inclusive) and the modulus (exclusive). - signed_residue
-
The object method
$x->signed_residue
returns a representative of the residue class the object represents, chosen as close to zero as possible. In case of a tie, i.e. when the modulus is an even number and the residue is half the modulus, the negative value is given preference (like in many native signed integer formats). - is_zero
- is_not_zero
-
The object methods
$x->is_zero
and$x->is_not_zero
return boolean values checking whether$x
is the zero element of its ring, i.e.0 == $x->residue
). Either one of these methods can be called implicitly when a Math::ModInt object is being used in boolean context. - as_string
-
The object method
$x->as_string
returns a string representation of$x
. It will be in the formmod(residue, modulus)
(similar to the constructor) in case of proper residue classes, ormod(?, ?)
in case of theundefined
placeholder.
Miscellaneous methods
- optimize_time
-
Some implementations can employ different optimization strategys for either time or space efficiency. Time efficiency aims to speed up repetitive calculations at the expense of memory space. Space efficiency aims to minimize the memory footprint at the expense of cpu cycles. Where such a distinction is available, separate choices can be made for each modulus.
The object method
$x->optimize_time
gives a hint to the implementation of$x
to prefer time over space efficiency for the modulus of$x
. It returns the object it was called with. - optimize_space
-
The object method
$x->optimize_space
gives a hint to the implementation of$x
to prefer space over time efficiency for the modulus of$x
. It returns the object it was called with. - optimize_default
-
The object method
$x->optimize_default
restores the default behaviour of the implementation of$x
with respect to its optimization strategy for the modulus of$x
. It returns the object it was called with. Defaults may depend on the modulus and may or may not be equivalent to one of the other strategy choices. They should, however, be reasonably secure to use on small systems, and thus lean more to space than time efficency.
Implementation Interface
Math::ModInt offers a special interface for implementations, intended to simplify operator overloading. Implementations are subclasses overriding only a couple of methods, as listed below. The overload pragma should not explicitly be used in implementations adhering to this interface.
Implementations handle a restricted set of moduli, sometimes only one. Currently, these restrictions are known in the base module and hard-coded there. Future revisions of Math::ModInt may offer a registration mechanism with precedences to make platform-specific choices possible.
Mandatory Methods
- residue
-
This method should return the normalized residue as defined in the application interface.
- modulus
-
This method should return the modulus as defined in the application interface.
- _NEW
-
This constructor will be called either as a class method with two parameters residue and modulus, or as an object method with just one parameter residue. It should return a new object with the given residue and modulus in the former case, or the given residue and the modulus of the invocant object in the latter case.
Note that the constructors mod and new of the application interface should not be overriden, as they need to switch implementations, depending on parameters rather than the package they are called from.
- _NEG
-
$x->_NEG
should return a new object representing-$x
. - _INV
-
$x->_INV
should return a new object representing the modular inverse of$x
, if it exists, otherwiseMath::ModInt->undefined
. - _ADD
-
$x->_ADD($y)
should return a new object representing$x+$y
. The parameter$y
will always be an object of the same class and have the same modulus as$x
. - _SUB
-
$x->_SUB($y)
should return a new object representing$x-$y
. The parameter$y
will always be an object of the same class and have the same modulus as$x
. - _MUL
-
$x->_MUL($y)
should return a new object representing$x*$y
. The parameter$y
will always be an object of the same class and have the same modulus as$x
. - _DIV
-
$x->_DIV($y)
should return a new object representing$x/$y
if it exists, otherwiseMath::ModInt->undefined
. The parameter$y
will always be an object of the same class and have the same modulus as$x
. - _POW
-
$x->_POW($y)
should return a new object representing$x ** $y
if it exists, otherwiseMath::ModInt->undefined
. The exponent$y
will always be an integer number. An undefined result means that the exponent was negative while$x
had no modular inverse.
Optional Methods
- optimize_time
- optimize_space
- optimize_default
-
These methods give hints for the optimization strategy for a particular modulus, as described in the application interface above. They do not need to be implemented.
DIAGNOSTICS
Some operations are not defined for all operands. For instance, division only makes sense if the denominator residue is coprime to the modulus. Operands with different moduli generally can not be combined in binary operations.
By default, operations with incompatible operands consistently yield the Math::Polynomial->undefined object, which will raise an exception upon modulus/residue inspection, but can be recogized by the boolean result of the is_defined/is_undefined methods.
DEPENDENCIES
This module uses Math::BigInt for arbitrary-precision calculations. If you want control over which Math::BigInt backend is to be used, import Math::BigInt before Math::ModInt, like this:
use Math::BigInt try => 'GMP,Pari';
use Math::ModInt qw(mod);
BUGS AND LIMITATIONS
So far, only a limited amount of effort has been put into making this module suite faster. We prefer native integer arithmetic over Math::BigInt only where it seems really save to do so, and we memoize only to little extent.
The event handling stuff, on the other hand, may already be coming close to overkill.
Currently, the choice of Math::ModInt backend is hard-wired into the main module, for the sake of simplicity. Please contact the maintainer if you intend to use a backend not from this distribution, so that something clever can be done about it.
At the time of release, extensive tests on various platforms will not yet have been performed, as it is precisely the purpose of this initial version to get out there in the first place. The suite therefore can be expected to break somewhere for sure. The author is looking forward to receive helpful reports, as well as more tests and examples. You may want to look out for updates for a while before making your enterprise depend on these modules. Even then, note the usual disclaimer.
If you find something cool you can do with Math::ModInt you like to share with others, you are welcome to submit your code for the examples section, as well as your name or chosen identity for the hall of fame.
Please submit your bug reports and suggestions through the CPAN RT, http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Math-ModInt .
SEE ALSO
The subject "modular arithmetic" on Wikipedia. http://en.wikipedia.org/wiki/Modular_arithmetic
AUTHOR
Martin Becker, <becker-cpan-mp@cozap.com>
ACKNOWLEDGEMENTS
Thanks go to Ilya Zakharevich for the overload package, and for mentioning this package ages before it was actually written, in perlnumber.pod.
LICENSE AND COPYRIGHT
Copyright (c) 2009-2010 by Martin Becker. All rights reserved.
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.6.0 or, at your option, any later version of Perl 5 you may have available.
DISCLAIMER OF WARRANTY
This library is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose.