mp.h revision 31de2854
1/*
2 * Copyright (c) 2002 by The XFree86 Project, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 *
22 * Except as contained in this notice, the name of the XFree86 Project shall
23 * not be used in advertising or otherwise to promote the sale, use or other
24 * dealings in this Software without prior written authorization from the
25 * XFree86 Project.
26 *
27 * Author: Paulo César Pereira de Andrade
28 */
29
30/* $XFree86: xc/programs/xedit/lisp/mp/mp.h,v 1.5tsi Exp $ */
31
32#include <stdio.h>
33#include <math.h>
34#ifdef sun
35#include <ieeefp.h>
36#endif
37#include <float.h>
38#include <stdlib.h>
39#include <limits.h>
40#include <ctype.h>
41#include <string.h>
42
43#ifndef __mp_h_
44#define __mp_h_
45
46#ifdef __GNUC__
47#define INLINE __inline__
48#else
49#define INLINE /**/
50#endif
51
52/* this normally is better for multiplication and also
53 * simplify addition loops putting the larger value first */
54#define MP_SWAP(op1, op2, len1, len2) {	\
55    BNS *top = op1;			\
56    BNI tlen = len1;			\
57					\
58    op1 = op2;				\
59    len1 = len2;			\
60    op2 = top;				\
61    len2 = tlen;			\
62}
63
64/*
65 * At least this length to use Karatsuba multiplication method
66 */
67#define KARATSUBA		32
68
69/*
70 * At least this length to use Toom multiplication method
71 */
72#define TOOM			128
73
74#if ULONG_MAX > 4294967295UL
75  /* sizeof(long) == 8 and sizeof(int) == 4 */
76# define BNI		unsigned long
77# define BNS		unsigned int
78# define MINSLONG	0x8000000000000000UL
79# define MAXSLONG	0x7fffffffffffffffUL
80# define CARRY		0x100000000
81# define LMASK		0xffffffff00000000UL
82# define SMASK		0x00000000ffffffffUL
83# define BNIBITS	64
84# define BNSBITS	32
85# ifndef LONG64
86#  define LONG64
87# endif
88#else
89  /* sizeof(long) == 4 and sizeof(short) == 2 */
90# define BNI		unsigned long
91# define BNS		unsigned short
92# define MINSLONG	0x80000000UL
93# define MAXSLONG	0x7fffffffUL
94# define CARRY		0x10000
95# define LMASK		0xffff0000UL
96# define SMASK		0x0000ffffUL
97# define BNIBITS	32
98# define BNSBITS	16
99#endif
100
101#ifdef MAX
102#undef MAX
103#endif
104#define MAX(a, b)	((a) > (b) ? (a) : (b))
105
106#ifdef MIN
107#undef MIN
108#endif
109#define MIN(a, b)	((a) < (b) ? (a) : (b))
110
111/*
112 * Types
113 */
114typedef struct _mpi {
115    unsigned int size : 31;
116    unsigned int sign : 1;
117    BNI alloc;
118    BNS *digs;		/* LSF format */
119} mpi;
120
121typedef struct _mpr {
122    mpi num;
123    mpi den;
124} mpr;
125
126typedef void *(*mp_malloc_fun)(size_t);
127typedef void *(*mp_calloc_fun)(size_t, size_t);
128typedef void *(*mp_realloc_fun)(void*, size_t);
129typedef void (*mp_free_fun)(void*);
130
131/*
132 * Prototypes
133 */
134/* GENERIC FUNCTIONS */
135	/* memory allocation wrappers */
136void *mp_malloc(size_t size);
137void *mp_calloc(size_t nmemb, size_t size);
138void *mp_realloc(void *pointer, size_t size);
139void mp_free(void *pointer);
140mp_malloc_fun mp_set_malloc(mp_malloc_fun);
141mp_calloc_fun mp_set_calloc(mp_calloc_fun);
142mp_realloc_fun mp_set_realloc(mp_realloc_fun);
143mp_free_fun mp_set_free(mp_free_fun);
144
145	/* adds op1 and op2, stores result in rop
146	 * rop must pointer to at least len1 + len2 + 1 elements
147	 * rop can be either op1 or op2 */
148long mp_add(BNS *rop, BNS *op1, BNS *op2, BNI len1, BNI len2);
149
150	/* subtracts op2 from op1, stores result in rop
151	 * rop must pointer to at least len1 + len2 elements
152	 * op1 must be >= op2
153	 * rop can be either op1 or op2 */
154long mp_sub(BNS *rop, BNS *op1, BNS *op2, BNI len1, BNI len2);
155
156	/* shift op to the left shift bits
157	 * rop must have enough storage for result
158	 * rop can be op */
159long mp_lshift(BNS *rop, BNS *op, BNI len, long shift);
160
161	/* shift op to the right shift bits
162	 * shift must be positive
163	 * rop can be op */
164long mp_rshift(BNS *rop, BNS *op, BNI len, long shift);
165
166	/* use simple generic multiplication method
167	 * rop cannot be the same as op1 or op2
168	 * rop must be zeroed
169	 * op1 can be op2 */
170long mp_base_mul(BNS *rop, BNS *op1, BNS *op2, BNI len1, BNI len2);
171
172	/* use Karatsuba method
173	 * MIN(len1, len2) must be larger than (MAX(len1, len2) + 1) >> 1
174	 * MAX(len1, len2) should be at least 2
175	 * rop cannot be the same as op1 or op2
176	 * rop must be zeroed
177	 * op1 can be op2 */
178long mp_karatsuba_mul(BNS *rop, BNS *op1, BNS *op2, BNI len1, BNI len2);
179
180	/* use Toom method
181	 * len1 / 3 should be equal to len2 / 3
182	 * len1 / 3 should be at least 1
183	 * rop cannot be the same as op1 or op2
184	 * rop must be zeroed
185	 * op1 can be op2 */
186long mp_toom_mul(BNS *rop, BNS *op1, BNS *op2, BNI len1, BNI len2);
187
188	/* chooses the available multiplication methods based on it's input
189	 * rop must be a pointer to len1 + len2 elements
190	 * rop cannot be the same as op1 or op2
191	 * rop must be zeroed
192	 * op1 can be op2 */
193long mp_mul(BNS *rop, BNS *op1, BNS *op2, BNI len1, BNI len2);
194
195/* INTEGER FUNCTIONS */
196	/* initialize op and set it to 0 */
197void mpi_init(mpi *op);
198
199	/* clear memory associated to op */
200void mpi_clear(mpi *op);
201
202	/* set rop to the value of op */
203void mpi_set(mpi *rop, mpi *op);
204
205	/* set rop to the value of si */
206void mpi_seti(mpi *rop, long si);
207
208	/* set rop to the floor(fabs(d)) */
209void mpi_setd(mpi *rop, double d);
210
211	/* initialize rop to number representation in str in the given base.
212	 * leading zeros are skipped.
213	 * if sign present, it is processed.
214	 * base must be in the range 2 to 36. */
215void mpi_setstr(mpi *rop, char *str, int base);
216
217	/* adds two mp integers */
218void mpi_add(mpi *rop, mpi *op1, mpi *op2);
219
220	/* adds op1 and op2 */
221void mpi_addi(mpi *rop, mpi *op1, long op2);
222
223	/* subtracts two mp integers */
224void mpi_sub(mpi *rop, mpi *op1, mpi *op2);
225
226	/* subtracts op2 from op1 */
227void mpi_subi(mpi *rop, mpi *op1, long op2);
228
229	/* multiply two mp integers */
230void mpi_mul(mpi *rop, mpi *op1, mpi *op2);
231
232	/* multiply op1 by op2 */
233void mpi_muli(mpi *rop, mpi *op1, long op2);
234
235	/* divides num by den and sets rop to result */
236void mpi_div(mpi *rop, mpi *num, mpi *den);
237
238	/* divides num by den and sets rop to the remainder */
239void mpi_rem(mpi *rop, mpi *num, mpi *den);
240
241	/* divides num by den, sets quotient to qrop and remainder to rrop
242	 * qrop is truncated towards zero.
243	 * qrop and rrop are optional
244	 * qrop and rrop cannot be the same variable */
245void mpi_divqr(mpi *qrop, mpi *rrop, mpi *num, mpi *den);
246
247	/* divides num by then and stores result in rop */
248void mpi_divi(mpi *rop, mpi *num, long den);
249
250	/* divides num by den and returns remainder */
251long mpi_remi(mpi *num, long den);
252
253	/* divides num by den
254	 * stores quotient in qrop and returns remainder */
255long mpi_divqri(mpi *qrop, mpi *num, long den);
256
257	/* sets rop to num modulo den */
258void mpi_mod(mpi *rop, mpi *num, mpi *den);
259
260	/* returns num modulo den */
261long mpi_modi(mpi *num, long den);
262
263	/* sets rop to the greatest common divisor of num and den
264	 * result is always positive */
265void mpi_gcd(mpi *rop, mpi *num, mpi *den);
266
267	/* sets rop to the least common multiple of num and den
268	 * result is always positive */
269void mpi_lcm(mpi *rop, mpi *num, mpi *den);
270
271	/* sets rop to op raised to exp */
272void mpi_pow(mpi *rop, mpi *op, unsigned long exp);
273
274	/* sets rop to the integer part of the nth root of op.
275	 * returns 1 if result is exact, 0 otherwise */
276int mpi_root(mpi *rop, mpi *op, unsigned long nth);
277
278	/* sets rop to the integer part of the square root of op.
279	 * returns 1 if result is exact, 0 otherwise */
280int mpi_sqrt(mpi *rop, mpi *op);
281
282	/* bit shift, left if shift positive, right if negative
283	 * a fast way to multiply and divide by powers of two */
284void mpi_ash(mpi *rop, mpi *op, long shift);
285
286	/* sets rop to op1 logand op2 */
287void mpi_and(mpi *rop, mpi *op1, mpi *op2);
288
289	/* sets rop to op1 logior op2 */
290void mpi_ior(mpi *rop, mpi *op1, mpi *op2);
291
292	/* sets rop to op1 logxor op2 */
293void mpi_xor(mpi *rop, mpi *op1, mpi *op2);
294
295	/* sets rop to one's complement of op */
296void mpi_com(mpi *rop, mpi *op);
297
298	/* sets rop to -op */
299void mpi_neg(mpi *rop, mpi *op);
300
301	/* sets rop to the absolute value of op */
302void mpi_abs(mpi *rop, mpi *op);
303
304	/* compares op1 and op2
305	 * returns >0 if op1 > op2, 0 if op1 = op2, and  <0 if op1 < op2 */
306int mpi_cmp(mpi *op1, mpi *op2);
307
308	/* mpi_cmp with a long integer operand */
309int mpi_cmpi(mpi *op1, long op2);
310
311	/* compares absolute value of op1 and op2
312	 * returns >0 if abs(op1) > abs(op2), 0 if abs(op1) = abs(op2),
313	 * and  <0 if abs(op1) < abs(op2) */
314int mpi_cmpabs(mpi *op1, mpi *op2);
315
316	/* mpi_cmpabs with a long integer operand */
317int mpi_cmpabsi(mpi *op1, long op2);
318
319	/* returns 1 if op1 > 0, 0 if op1 = 0, and  -1 if op1 < 0 */
320int mpi_sgn(mpi *op);
321
322	/* fastly swaps contents of op1 and op2 */
323void mpi_swap(mpi *op1, mpi *op2);
324
325	/* returns 1 if op fits in a signed long int, 0 otherwise */
326int mpi_fiti(mpi *op);
327
328	/* converts mp integer to long int
329	 * to know if the value will fit, call mpi_fiti */
330long mpi_geti(mpi *op);
331
332	/* convert mp integer to double */
333double mpi_getd(mpi *op);
334
335	/* returns exact number of characters to represent mp integer
336	 * in given base, excluding sign and ending null character.
337	 * base must be in the range 2 to 36 */
338unsigned long mpi_getsize(mpi *op, int base);
339
340	/* returns pointer to string with representation of mp integer
341	 * if str is not NULL, it must have enough space to store integer
342	 * representation, if NULL a newly allocated string is returned.
343	 * base must be in the range 2 to 36 */
344char *mpi_getstr(char *str, mpi *op, int base);
345
346/* RATIO FUNCTIONS */
347#define mpr_num(op)	(&((op)->num))
348#define mpr_den(op)	(&((op)->den))
349
350	/* initialize op and set it to 0/1 */
351void mpr_init(mpr *op);
352
353	/* clear memory associated to op */
354void mpr_clear(mpr *op);
355
356	/* set rop to the value of op */
357void mpr_set(mpr *rop, mpr *op);
358
359	/* set rop to num/den */
360void mpr_seti(mpr *rop, long num, long den);
361
362	/* set rop to the value of d */
363void mpr_setd(mpr *rop, double d);
364
365	/* initialize rop to number representation in str in the given base.
366	 * leading zeros are skipped.
367	 * if sign present, it is processed.
368	 * base must be in the range 2 to 36. */
369void mpr_setstr(mpr *rop, char *str, int base);
370
371	/* remove common factors of op */
372void mpr_canonicalize(mpr *op);
373
374	/* adds two mp rationals */
375void mpr_add(mpr *rop, mpr *op1, mpr *op2);
376
377	/* adds op1 and op2 */
378void mpr_addi(mpr *rop, mpr *op1, long op2);
379
380	/* subtracts two mp rationals */
381void mpr_sub(mpr *rop, mpr *op1, mpr *op2);
382
383	/* subtracts op2 from op1 */
384void mpr_subi(mpr *rop, mpr *op1, long op2);
385
386	/* multiply two mp rationals */
387void mpr_mul(mpr *rop, mpr *op1, mpr *op2);
388
389	/* multiply op1 by op2 */
390void mpr_muli(mpr *rop, mpr *op1, long op2);
391
392	/* divide two mp rationals */
393void mpr_div(mpr *rop, mpr *op1, mpr *op2);
394
395	/* divides op1 by op2 */
396void mpr_divi(mpr *rop, mpr *op1, long op2);
397
398	/* sets rop to 1/op */
399void mpr_inv(mpr *rop, mpr *op);
400
401	/* sets rop to -op */
402void mpr_neg(mpr *rop, mpr *op);
403
404	/* sets rop to the absolute value of op */
405void mpr_abs(mpr *rop, mpr *op);
406
407	/* compares op1 and op2
408	 * returns >0 if op1 > op2, 0 if op1 = op2, and  <0 if op1 < op2 */
409int mpr_cmp(mpr *op1, mpr *op2);
410
411	/* mpr_cmp with a long integer operand */
412int mpr_cmpi(mpr *op1, long op2);
413
414	/* compares absolute value of op1 and op2
415	 * returns >0 if abs(op1) > abs(op2), 0 if abs(op1) = abs(op2),
416	 * and  <0 if abs(op1) < abs(op2) */
417int mpr_cmpabs(mpr *op1, mpr *op2);
418
419	/* mpr_cmpabs with a long integer operand */
420int mpr_cmpabsi(mpr *op1, long op2);
421
422	/* fastly swaps contents of op1 and op2 */
423void mpr_swap(mpr *op1, mpr *op2);
424
425	/* returns 1 if op fits in a signed long int, 0 otherwise */
426int mpr_fiti(mpr *op);
427
428	/* convert mp rational to double */
429double mpr_getd(mpr *op);
430
431	/* returns pointer to string with representation of mp rational
432	 * if str is not NULL, it must have enough space to store rational
433	 * representation, if NULL a newly allocated string is returned.
434	 * base must be in the range 2 to 36 */
435char *mpr_getstr(char *str, mpr *op, int base);
436
437#endif /* __mp_h_ */
438