801 lines
14 KiB
Text
801 lines
14 KiB
Text
.TH MP 2
|
|
.SH NAME
|
|
mpsetminbits, mpnew, mpfree, mpbits, mpnorm, mpcopy, mpassign, mprand, mpnrand, strtomp, mpfmt, mptoa, betomp, mptobe, mptober, letomp, mptole, mptolel, mptoui, uitomp, mptoi, itomp, uvtomp, mptouv, vtomp, mptov, mptod, dtomp, mpdigdiv, mpadd, mpsub, mpleft, mpright, mpmul, mpexp, mpmod, mpmodadd, mpmodsub, mpmodmul, mpdiv, mpcmp, mpsel, mpfactorial, mpextendedgcd, mpinvert, mpsignif, mplowbits0, mpvecdigmuladd, mpvecdigmulsub, mpvecadd, mpvecsub, mpveccmp, mpvecmul, mpmagcmp, mpmagadd, mpmagsub, crtpre, crtin, crtout, crtprefree, crtresfree \- extended precision arithmetic
|
|
.SH SYNOPSIS
|
|
.B #include <u.h>
|
|
.br
|
|
.B #include <libc.h>
|
|
.br
|
|
.B #include <mp.h>
|
|
.PP
|
|
.ta +\w'\fLCRTpre* \fP'u
|
|
.B
|
|
mpint* mpnew(int n)
|
|
.PP
|
|
.B
|
|
void mpfree(mpint *b)
|
|
.PP
|
|
.B
|
|
void mpsetminbits(int n)
|
|
.PP
|
|
.B
|
|
void mpbits(mpint *b, int n)
|
|
.PP
|
|
.B
|
|
mpint* mpnorm(mpint *b)
|
|
.PP
|
|
.B
|
|
mpint* mpcopy(mpint *b)
|
|
.PP
|
|
.B
|
|
void mpassign(mpint *old, mpint *new)
|
|
.PP
|
|
.B
|
|
mpint* mprand(int bits, void (*gen)(uchar*, int), mpint *b)
|
|
.PP
|
|
.B
|
|
mpint* mpnrand(mpint *n, void (*gen)(uchar*, int), mpint *b)
|
|
.PP
|
|
.B
|
|
mpint* strtomp(char *buf, char **rptr, int base, mpint *b)
|
|
.PP
|
|
.B
|
|
char* mptoa(mpint *b, int base, char *buf, int blen)
|
|
.PP
|
|
.B
|
|
int mpfmt(Fmt*)
|
|
.PP
|
|
.B
|
|
mpint* betomp(uchar *buf, uint blen, mpint *b)
|
|
.PP
|
|
.B
|
|
int mptobe(mpint *b, uchar *buf, uint blen, uchar **bufp)
|
|
.PP
|
|
.B
|
|
void mptober(mpint *b, uchar *buf, int blen)
|
|
.PP
|
|
.B
|
|
mpint* letomp(uchar *buf, uint blen, mpint *b)
|
|
.PP
|
|
.B
|
|
int mptole(mpint *b, uchar *buf, uint blen, uchar **bufp)
|
|
.PP
|
|
.B
|
|
void mptolel(mpint *b, uchar *buf, int blen)
|
|
.PP
|
|
.B
|
|
uint mptoui(mpint*)
|
|
.PP
|
|
.B
|
|
mpint* uitomp(uint, mpint*)
|
|
.PP
|
|
.B
|
|
int mptoi(mpint*)
|
|
.PP
|
|
.B
|
|
mpint* itomp(int, mpint*)
|
|
.PP
|
|
.B
|
|
mpint* vtomp(vlong, mpint*)
|
|
.PP
|
|
.B
|
|
vlong mptov(mpint*)
|
|
.PP
|
|
.B
|
|
mpint* uvtomp(uvlong, mpint*)
|
|
.PP
|
|
.B
|
|
uvlong mptouv(mpint*)
|
|
.PP
|
|
.B
|
|
mpint* dtomp(double, mpint*)
|
|
.PP
|
|
.B
|
|
double mptod(mpint*)
|
|
.PP
|
|
.B
|
|
void mpadd(mpint *b1, mpint *b2, mpint *sum)
|
|
.PP
|
|
.B
|
|
void mpmagadd(mpint *b1, mpint *b2, mpint *sum)
|
|
.PP
|
|
.B
|
|
void mpsub(mpint *b1, mpint *b2, mpint *diff)
|
|
.PP
|
|
.B
|
|
void mpmagsub(mpint *b1, mpint *b2, mpint *diff)
|
|
.PP
|
|
.B
|
|
void mpleft(mpint *b, int shift, mpint *res)
|
|
.PP
|
|
.B
|
|
void mpright(mpint *b, int shift, mpint *res)
|
|
.PP
|
|
.B
|
|
void mpand(mpint *b1, mpint *b2, mpint *res)
|
|
.PP
|
|
.B
|
|
void mpbic(mpint *b1, mpint *b2, mpint *res)
|
|
.PP
|
|
.B
|
|
void mpor(mpint *b1, mpint *b2, mpint *res)
|
|
.PP
|
|
.B
|
|
void mpnot(mpint *b, mpint *res)
|
|
.PP
|
|
.B
|
|
void mpxor(mpint *b1, mpint *b2, mpint *res)
|
|
.PP
|
|
.B
|
|
void mptrunc(mpint *b, int n, mpint *res)
|
|
.PP
|
|
.B
|
|
void mpxtend(mpint *b, int n, mpint *res)
|
|
.PP
|
|
.B
|
|
void mpasr(mpint *b, int n, mpint *res)
|
|
.PP
|
|
.B
|
|
void mpmul(mpint *b1, mpint *b2, mpint *prod)
|
|
.PP
|
|
.B
|
|
void mpexp(mpint *b, mpint *e, mpint *m, mpint *res)
|
|
.PP
|
|
.B
|
|
void mpmod(mpint *b, mpint *m, mpint *remainder)
|
|
.PP
|
|
.B
|
|
void mpdiv(mpint *dividend, mpint *divisor, mpint *quotient,
|
|
.br
|
|
.B
|
|
mpint *remainder)
|
|
.PP
|
|
.B
|
|
void mpmodadd(mpint *b1, mpint *b2, mpint *m, mpint *sum)
|
|
.PP
|
|
.B
|
|
void mpmodsub(mpint *b1, mpint *b2, mpint *m, mpint *diff)
|
|
.PP
|
|
.B
|
|
void mpmodmul(mpint *b1, mpint *b2, mpint *m, mpint *prod)
|
|
.PP
|
|
.B
|
|
int mpcmp(mpint *b1, mpint *b2)
|
|
.PP
|
|
.B
|
|
int mpmagcmp(mpint *b1, mpint *b2)
|
|
.PP
|
|
.B
|
|
void mpsel(int s, mpint *b1, mpint *b2, mpint *res)
|
|
.PP
|
|
.B
|
|
mpint* mpfactorial(ulong n)
|
|
.PP
|
|
.B
|
|
void mpextendedgcd(mpint *a, mpint *b, mpint *d, mpint *x,
|
|
.br
|
|
.B
|
|
mpint *y)
|
|
.PP
|
|
.B
|
|
void mpinvert(mpint *b, mpint *m, mpint *res)
|
|
.PP
|
|
.B
|
|
int mpsignif(mpint *b)
|
|
.PP
|
|
.B
|
|
int mplowbits0(mpint *b)
|
|
.PP
|
|
.B
|
|
void mpdigdiv(mpdigit *dividend, mpdigit divisor,
|
|
.br
|
|
.B
|
|
mpdigit *quotient)
|
|
.PP
|
|
.B
|
|
void mpvecadd(mpdigit *a, int alen, mpdigit *b, int blen,
|
|
.br
|
|
.B
|
|
mpdigit *sum)
|
|
.PP
|
|
.B
|
|
void mpvecsub(mpdigit *a, int alen, mpdigit *b, int blen,
|
|
.br
|
|
.B
|
|
mpdigit *diff)
|
|
.PP
|
|
.B
|
|
void mpvecdigmuladd(mpdigit *b, int n, mpdigit m, mpdigit *p)
|
|
.PP
|
|
.B
|
|
int mpvecdigmulsub(mpdigit *b, int n, mpdigit m, mpdigit *p)
|
|
.PP
|
|
.B
|
|
void mpvecmul(mpdigit *a, int alen, mpdigit *b, int blen,
|
|
.br
|
|
.B
|
|
mpdigit *p)
|
|
.PP
|
|
.B
|
|
int mpveccmp(mpdigit *a, int alen, mpdigit *b, int blen)
|
|
.PP
|
|
.B
|
|
CRTpre* crtpre(int nfactors, mpint **factors)
|
|
.PP
|
|
.B
|
|
CRTres* crtin(CRTpre *crt, mpint *x)
|
|
.PP
|
|
.B
|
|
void crtout(CRTpre *crt, CRTres *r, mpint *x)
|
|
.PP
|
|
.B
|
|
void crtprefree(CRTpre *cre)
|
|
.PP
|
|
.B
|
|
void crtresfree(CRTres *res)
|
|
.PP
|
|
.B
|
|
mpint *mpzero, *mpone, *mptwo
|
|
.DT
|
|
.SH DESCRIPTION
|
|
These routines perform extended precision integer arithmetic.
|
|
The basic type is
|
|
.BR mpint ,
|
|
which points to an array of
|
|
.BR mpdigit s,
|
|
stored in little-endian order:
|
|
.IP
|
|
.EX
|
|
typedef struct mpint mpint;
|
|
struct mpint
|
|
{
|
|
int sign; /* +1 or -1 */
|
|
int size; /* allocated digits */
|
|
int top; /* significant digits */
|
|
mpdigit *p;
|
|
char flags;
|
|
};
|
|
.EE
|
|
.PP
|
|
The sign of 0 is +1.
|
|
.PP
|
|
The size of
|
|
.B mpdigit
|
|
is architecture-dependent and defined in
|
|
.BR /$cputype/include/u.h .
|
|
.BR Mpint s
|
|
are dynamically allocated and must be explicitly freed. Operations
|
|
grow the array of digits as needed.
|
|
.PP
|
|
In general, the result parameters are last in the
|
|
argument list.
|
|
.PP
|
|
Routines that return an
|
|
.B mpint
|
|
will allocate the
|
|
.B mpint
|
|
if the result parameter is
|
|
.BR nil .
|
|
This includes
|
|
.IR strtomp ,
|
|
.IR itomp ,
|
|
.IR uitomp ,
|
|
.IR btomp ,
|
|
and
|
|
.IR dtomp .
|
|
These functions, in addition to
|
|
.I mpnew
|
|
and
|
|
.IR mpcopy ,
|
|
will return
|
|
.B nil
|
|
if the allocation fails.
|
|
.PP
|
|
Input and result parameters may point to the same
|
|
.BR mpint .
|
|
The routines check and copy where necessary.
|
|
.PP
|
|
.I Mpnew
|
|
creates an
|
|
.B mpint
|
|
with an initial allocation of
|
|
.I n
|
|
bits.
|
|
If
|
|
.I n
|
|
is zero, the allocation will be whatever was specified in the
|
|
last call to
|
|
.I mpsetminbits
|
|
or to the initial value, 1056.
|
|
.I Mpfree
|
|
frees an
|
|
.BR mpint .
|
|
.I Mpbits
|
|
grows the allocation of
|
|
.I b
|
|
to fit at least
|
|
.I n
|
|
bits. If
|
|
.B b->top
|
|
doesn't cover
|
|
.I n
|
|
bits,
|
|
.I mpbits
|
|
increases it to do so.
|
|
Unless you are writing new basic operations, you
|
|
can restrict yourself to
|
|
.B mpnew(0)
|
|
and
|
|
.BR mpfree(b) .
|
|
.PP
|
|
.I Mpnorm
|
|
normalizes the representation by trimming any high order zero
|
|
digits. All routines except
|
|
.B mpbits
|
|
return normalized results.
|
|
.PP
|
|
.I Mpcopy
|
|
creates a new
|
|
.B mpint
|
|
with the same value as
|
|
.I b
|
|
while
|
|
.I mpassign
|
|
sets the value of
|
|
.I new
|
|
to be that of
|
|
.IR old .
|
|
.PP
|
|
.I Mprand
|
|
creates an
|
|
.I n
|
|
bit random number using the generator
|
|
.IR gen .
|
|
.I Gen
|
|
takes a pointer to a string of uchar's and the number
|
|
to fill in.
|
|
.PP
|
|
.I Mpnrand
|
|
uses
|
|
.I gen
|
|
to generate a uniform random number
|
|
.IR x ,
|
|
.if t 0 ≤ \fIx\fR < \fIn\fR.
|
|
.if n 0 ≤ x < n.
|
|
.PP
|
|
.I Strtomp
|
|
and
|
|
.I mptoa
|
|
convert between
|
|
.SM ASCII
|
|
and
|
|
.B mpint
|
|
representations using the base indicated.
|
|
Only the bases 2, 4, 8, 10, 16, 32, and 64 are
|
|
supported.
|
|
.IR Strtomp
|
|
skips any leading spaces or tabs.
|
|
.IR Strtomp 's
|
|
scan stops when encountering a digit not valid in the
|
|
base. If
|
|
.I base
|
|
is zero then C-style prefixes are interpreted to
|
|
find the base:
|
|
.B 0x
|
|
for hexadecimal,
|
|
.B 0b
|
|
for binary and
|
|
.B 0
|
|
for octal. Otherwise decimal is assumed.
|
|
.I rptr
|
|
is not zero,
|
|
.I *rptr
|
|
is set to point to the character immediately after the
|
|
string converted.
|
|
If the parse terminates before any digits are found,
|
|
.I strtomp
|
|
return
|
|
.BR nil .
|
|
.I Mptoa
|
|
returns a pointer to the
|
|
.SM ASCII
|
|
filled buffer.
|
|
If the parameter
|
|
.I buf
|
|
is
|
|
.BR nil ,
|
|
the buffer is allocated.
|
|
Setting
|
|
.I base
|
|
to zero uses hexadecimal default.
|
|
.I Mpfmt
|
|
can be used with
|
|
.IR fmtinstall (2)
|
|
and
|
|
.IR print (2)
|
|
to print
|
|
.SM ASCII
|
|
representations of
|
|
.BR mpint s.
|
|
The conventional verb is
|
|
.LR B ,
|
|
for which
|
|
.I mp.h
|
|
provides a
|
|
.LR pragma .
|
|
The precision in the format string changes the base,
|
|
defaulting to hexadecimal when omited.
|
|
.PP
|
|
.I Mptobe
|
|
and
|
|
.I mptole
|
|
convert an
|
|
.I mpint
|
|
to a byte array. The former creates a big endian representation,
|
|
the latter a little endian one.
|
|
If the destination
|
|
.I buf
|
|
is not
|
|
.BR nil ,
|
|
it specifies the buffer of length
|
|
.I blen
|
|
for the result. If the representation
|
|
is less than
|
|
.I blen
|
|
bytes, the rest of the buffer is zero filled.
|
|
If
|
|
.I buf
|
|
is
|
|
.BR nil ,
|
|
then a buffer is allocated and a pointer to it is
|
|
deposited in the location pointed to by
|
|
.IR bufp .
|
|
Sign is ignored in these conversions, i.e., the byte
|
|
array version is always positive.
|
|
.PP
|
|
.I Mptober
|
|
and
|
|
.I mptolel
|
|
fill
|
|
.I blen
|
|
lower bytes of an
|
|
.I mpint
|
|
into a fixed length byte array.
|
|
.I Mptober
|
|
fills the bytes right adjusted in big endian order so that the least
|
|
significant byte is at
|
|
.I buf[blen-1]
|
|
while
|
|
.I mptolel
|
|
fills in little endian order; left adjusted; so that the least
|
|
significat byte is filled into
|
|
.IR buf[0] .
|
|
.PP
|
|
.IR Betomp ,
|
|
and
|
|
.I letomp
|
|
convert from a big or little endian byte array at
|
|
.I buf
|
|
of length
|
|
.I blen
|
|
to an
|
|
.IR mpint .
|
|
If
|
|
.I b
|
|
is not
|
|
.IR nil ,
|
|
it refers to a preallocated
|
|
.I mpint
|
|
for the result.
|
|
If
|
|
.I b
|
|
is
|
|
.BR nil ,
|
|
a new integer is allocated and returned as the result.
|
|
.PP
|
|
The integer (and floating point) conversions are:
|
|
.TF Mptouv
|
|
.TP
|
|
.I mptoui
|
|
.BR mpint -> "unsigned int"
|
|
.TP
|
|
.I uitomp
|
|
.BR "unsigned int" -> mpint
|
|
.TP
|
|
.I mptoi
|
|
.BR mpint -> "int"
|
|
.TP
|
|
.I itomp
|
|
.BR "int" -> mpint
|
|
.TP
|
|
.I mptouv
|
|
.BR mpint -> "unsigned vlong"
|
|
.TP
|
|
.I uvtomp
|
|
.BR "unsigned vlong" -> mpint
|
|
.TP
|
|
.I mptov
|
|
.BR mpint -> "vlong"
|
|
.TP
|
|
.I vtomp
|
|
.BR "vlong" -> mpint
|
|
.TP
|
|
.I mptod
|
|
.BR mpint -> "double"
|
|
.TP
|
|
.I dtomp
|
|
.BR "double" -> mpint
|
|
.PD
|
|
.PP
|
|
When converting to the base integer types, if the integer is too large,
|
|
the largest integer of the appropriate sign
|
|
and size is returned.
|
|
.PP
|
|
When converting to and from floating point, results are rounded using IEEE 754 "round to nearest".
|
|
If the integer is too large in magnitude,
|
|
.I mptod
|
|
returns infinity of the appropriate sign.
|
|
.PP
|
|
The mathematical functions are:
|
|
.TF mpfactorial
|
|
.TP
|
|
.I mpadd
|
|
.BR "sum = b1 + b2" .
|
|
.TP
|
|
.I mpmagadd
|
|
.BR "sum = abs(b1) + abs(b2)" .
|
|
.TP
|
|
.I mpsub
|
|
.BR "diff = b1 - b2" .
|
|
.TP
|
|
.I mpmagsub
|
|
.BR "diff = abs(b1) - abs(b2)" .
|
|
.TP
|
|
.I mpleft
|
|
.BR "res = b<<shift" .
|
|
.TP
|
|
.I mpright
|
|
.BR "res = b>>shift" .
|
|
.TP
|
|
.I mpmul
|
|
.BR "prod = b1*b2" .
|
|
.TP
|
|
.I mpexp
|
|
if
|
|
.I m
|
|
is nil,
|
|
.BR "res = b**e" .
|
|
Otherwise,
|
|
.BR "res = b**e mod m" .
|
|
.TP
|
|
.I mpmod
|
|
.BR "remainder = b % m" .
|
|
.TP
|
|
.I mpdiv
|
|
.BR "quotient = dividend/divisor" .
|
|
.BR "remainder = dividend % divisor" .
|
|
.TP
|
|
.I mpcmp
|
|
returns -1, 0, or +1 as
|
|
.I b1
|
|
is less than, equal to, or greater than
|
|
.IR b2 .
|
|
.TP
|
|
.I mpmagcmp
|
|
the same as
|
|
.I mpcmp
|
|
but ignores the sign and just compares magnitudes.
|
|
.TP
|
|
.I mpsel
|
|
assigns
|
|
.I b1
|
|
to
|
|
.I res
|
|
when
|
|
.I s
|
|
is not zero, otherwise
|
|
.I b2
|
|
is assigned to
|
|
.IR res .
|
|
.TP
|
|
.I mpfactorial
|
|
returns \fIn\fR!.
|
|
.PD
|
|
.PP
|
|
Logical operations (treating negative numbers using two's complement):
|
|
.TF mpxtend_
|
|
.TP
|
|
.I mpand
|
|
.BR "res = b1 & b2" .
|
|
.TP
|
|
.I mpbic
|
|
.BR "res = b1 & ~b2" .
|
|
.TP
|
|
.I mpor
|
|
.BR "res = b1 | b2" .
|
|
.TP
|
|
.I mpxor
|
|
.BR "res = b1 ^ b2" .
|
|
.TP
|
|
.I mpnot
|
|
.BR "res = ~b1" .
|
|
.TP
|
|
.I mpasr
|
|
.BR "res = b>>shift"
|
|
(\fImpasr\fR, unlike
|
|
.IR mpright ,
|
|
uses two's complement).
|
|
.TP
|
|
.I mptrunc
|
|
truncates
|
|
.I b
|
|
to
|
|
.I n
|
|
bits and stores the result in
|
|
.IR res .
|
|
The result is never negative.
|
|
.TP
|
|
.I mpxtend
|
|
truncates
|
|
.I b
|
|
to
|
|
.I n
|
|
bits, sign extends the MSB and stores the result in
|
|
.IR res .
|
|
.PD
|
|
.PP
|
|
Modular arithmetic:
|
|
.TF mpmodmul_
|
|
.TP
|
|
.I mpmodadd
|
|
.BR "sum = b1+b2 mod m" .
|
|
.TP
|
|
.I mpmodsub
|
|
.BR "diff = b1-b2 mod m" .
|
|
.TP
|
|
.I mpmodmul
|
|
.BR "prod = b1*b2 mod m" .
|
|
.PD
|
|
.PP
|
|
.I Mpextendedgcd
|
|
computes the greatest common denominator,
|
|
.IR d ,
|
|
of
|
|
.I a
|
|
and
|
|
.IR b .
|
|
It also computes
|
|
.I x
|
|
and
|
|
.I y
|
|
such that
|
|
.BR "a*x + b*y = d" .
|
|
Both
|
|
.I a
|
|
and
|
|
.I b
|
|
are required to be positive.
|
|
If called with negative arguments, it will
|
|
return a gcd of 0.
|
|
.PP
|
|
.I Mpinvert
|
|
computes the multiplicative inverse of
|
|
.I b
|
|
.B mod
|
|
.IR m .
|
|
.PP
|
|
.I Mpsignif
|
|
returns the number of significant bits in
|
|
.IR b .
|
|
.I Mplowbits0
|
|
returns the number of consecutive zero bits
|
|
at the low end of the significant bits.
|
|
For example, for 0x14,
|
|
.I mpsignif
|
|
returns 5 and
|
|
.I mplowbits0
|
|
returns 2.
|
|
For 0,
|
|
.I mpsignif
|
|
and
|
|
.I mplowbits0
|
|
both return 0.
|
|
.PP
|
|
The remaining routines all work on arrays of
|
|
.B mpdigit
|
|
rather than
|
|
.BR mpint 's.
|
|
They are the basis of all the other routines. They are separated out
|
|
to allow them to be rewritten in assembler for each architecture. There
|
|
is also a portable C version for each one.
|
|
.TF mpvecdigmuladd
|
|
.TP
|
|
.I mpdigdiv
|
|
.BR "quotient = dividend[0:1] / divisor" .
|
|
.TP
|
|
.I mpvecadd
|
|
.BR "sum[0:alen] = a[0:alen-1] + b[0:blen-1]" .
|
|
We assume alen >= blen and that sum has room for alen+1 digits.
|
|
.TP
|
|
.I mpvecsub
|
|
.BR "diff[0:alen-1] = a[0:alen-1] - b[0:blen-1]" .
|
|
We assume that alen >= blen and that diff has room for alen digits.
|
|
.TP
|
|
.I mpvecdigmuladd
|
|
.BR "p[0:n] += m * b[0:n-1]" .
|
|
This multiplies a an array of digits times a scalar and adds it to another array.
|
|
We assume p has room for n+1 digits.
|
|
.TP
|
|
.I mpvecdigmulsub
|
|
.BR "p[0:n] -= m * b[0:n-1]" .
|
|
This multiplies a an array of digits times a scalar and subtracts it from another array.
|
|
We assume p has room for n+1 digits. It returns +1 is the result is positive and
|
|
-1 if negative.
|
|
.TP
|
|
.I mpvecmul
|
|
.BR "p[0:alen+blen] = a[0:alen-1] * b[0:blen-1]" .
|
|
We assume that p has room for alen+blen+1 digits.
|
|
.TP
|
|
.I mpveccmp
|
|
This returns -1, 0, or +1 as a - b is negative, 0, or positive.
|
|
.PD
|
|
.PP
|
|
.IR mptwo ,
|
|
.I mpone
|
|
and
|
|
.I mpzero
|
|
are the constants 2, 1 and 0. These cannot be freed.
|
|
.SS "Time invariant computation"
|
|
.PP
|
|
In the field of cryptography, it is sometimes neccesary to implement
|
|
algorithms such that the runtime of the algorithm is not depdenent on
|
|
the input data. This library provides partial support for time
|
|
invariant computation with the
|
|
.I MPtimesafe
|
|
flag that can be set on input or destination operands to request timing
|
|
safe operation. The result of a timing safe operation will also have the
|
|
.I MPtimesafe
|
|
flag set and is not normalized.
|
|
.SS "Chinese remainder theorem
|
|
.PP
|
|
When computing in a non-prime modulus,
|
|
.IR n,
|
|
it is possible to perform the computations on the residues modulo the prime
|
|
factors of
|
|
.I n
|
|
instead. Since these numbers are smaller, multiplication and exponentiation
|
|
can be much faster.
|
|
.PP
|
|
.I Crtin
|
|
computes the residues of
|
|
.I x
|
|
and returns them in a newly allocated structure:
|
|
.IP
|
|
.EX
|
|
typedef struct CRTres CRTres;
|
|
{
|
|
int n; /* number of residues */
|
|
mpint *r[n]; /* residues */
|
|
};
|
|
.EE
|
|
.PP
|
|
.I Crtout
|
|
takes a residue representation of a number and converts it back into
|
|
the number. It also frees the residue structure.
|
|
.PP
|
|
.I Crepre
|
|
saves a copy of the factors and precomputes the constants necessary
|
|
for converting the residue form back into a number modulo
|
|
the product of the factors. It returns a newly allocated structure
|
|
containing values.
|
|
.PP
|
|
.I Crtprefree
|
|
and
|
|
.I crtresfree
|
|
free
|
|
.I CRTpre
|
|
and
|
|
.I CRTres
|
|
structures respectively.
|
|
.SH SOURCE
|
|
.B /sys/src/libmp
|