ape(3x)
NAME
ape − arbitrary precision integer arithmetic routines
SYNTAX
#include <ape.h>
cc ... −lape
f77 ... −lape
DESCRIPTION
The ape library is a set of routines for arbitrary precision integral arithmetic which may be called by either C or F77 programs.
The routines work on the structure MINT (“multiprecision integer”) defined by
typedef struct mint {
int len;
short *val;
} MINT, *PMINT;
The member len is an integer whose sign is the sign of the number represented, and whose magnitude is the number of words (short integers) needed to store it. The (absolute value of) the number itself is stored base 215 as an array of short ints pointed to by val. Space for this array is managed by calls to malloc(3) and free. The size of the numbers representable is limited only by the amount of core available; on a PDP-11/45, numbers of 40,000 digits have been successfully dealt with.
The routines themselves may be grouped into four categories:
INITIALIZATION AND REMOVAL
MINT pointers (PMINTs) must be initialized before they can be used by the other routines. Methods for doing this include:
new(pa)PMINT *pa;
PMINT shtom(sn)short sn;
PMINT itom(n)int n;
PMINT ltom(ln)long ln;
PMINT stom(s)char *s;
The new(&a) creates a zero MINT which a points to. The other functions return pointers to MINTs with values equal to their arguments (or to the numeric equivalent of its argument for stom). The stom routine follows the usual C conventions for determining the input base.
For freeing storage, two routines are provided:
xfree(a)
afree(a) PMINT a;
The xfree(a) frees what a->val points to, zeroing a; afree(a) also frees what a points to.
ARITHMETIC
For the following conceptual descriptions, assume these type declarations:
PMINT a,b,c,d,q,r;
int m,n;
long ln;
short *R;
RoutineResult
madd(a,b,c)c = a + b
msub(a,b,c)c = a - b
mult(a,b,c)c = a * b
sdiv(a,m,q,R)q = a / m; R = a mod m
mdiv(a,b,q,r)q = a / b; r = a mod b
gcd(a,b,c)c = gcd(a,b)
reciprocal(a,n,b)b = 10n / a
msqrt(a,b,r)b = √n
‾ r = a - b*b
[r’s length is returned]
pow(a,b,c,d)d = ab mod c
rpow(a,n,b)b = an
lpow(n,ln,b)b = nln
In all cases, calls like madd(a,b,a) are allowed and give the expected results. The routines dealing with ints will all work properly no matter what the relationship between short and int except sdiv which needs the int m to be no larger than the largest short. The reciprocal is the closest thing provided to decimal fractions.
Comparisons may be done with the function mcmp. The mcmp(a,b) returns something positive if a>b, negative if a<b, and zero if a=b.
INPUT AND OUTPUT
The following routines do input and output:
PMINT a;
int n; /* must have n > 1 */
FILE *f;
char *s;
m_in(a,n,f)
input a number base n from file f into a
sm_in(a,n,s)
input a number base n from string s into a
m_out(a,n,f)
output a base n onto file f
sm_out(a,n,s)
output a base n onto string s
The m_in returns 0 on normal termination, and EOF when the end of the input file is reached.
Special versions of these routines are provided for bases 8 and 10. They are:
PMINT a;
FILE *f;
Base 8
om_in(a,f)
omin(a)[f=stdin]
om_out(a,f)
omout(a)[f=stdout]
Base 10
fmin(a,f)
minput(a)[f=stdin]
fmout(a,f)
mout(a)[f=stdout]
F77 USAGE
“Frontend” subroutines are provided to allow F77 programs to use the ape routines. The calling program’s integers are cast into PMINTs by these subroutines and then passed to the appropriate ape routine.
The names and syntax of these subroutines are generally the same as their C counterparts. Exceptions are:
f77 versionC version
integer n,aint n; PMINT a;
character*M schar s[M];
call new(a)new(&a);
call itom(n,a)a = itom(n);
call stom(s,a)a = stom(s);
call minput(a,n)n = minput(a);
call omin(a,n)n = omin(a);
call mout(a)mout(a);
call omout(a)mout(a);
(no other I/O routines are provided)
Subroutines are also provided for conversions between the MINT structure and the Fortran-manipulable version of an integer and an array of integer*2’s:
integer a, length [a represents a PMINT]
integer*2 vector(N) [must have abs(length) .le. N]
call mtovec(a,length,vector)
results in:
length = a->len
for i = 1 to abs(length)
vector(i) = a->val[i-1]
call vectom(length,vector,a)
results in:
a->len = length
for i = 1 to abs(length)
a->val[i-1] = vector(i)
The latter is actually a method of initialization.
RESTRICTIONS
Input bases should be ≤ 35.
Octal input is slower than it need be.
Syntax is odd and storage management is a pain.
DIAGNOSTICS
Improper operations and running out of memory produce self-explanatory messages and gratuitous core dumps.
FILES
/usr/include/ape.h include file
/usr/lib/libape.a object code library