mathimp.c revision 5dfecf96
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/mathimp.c,v 1.14tsi Exp $ */
31
32
33/*
34 * Defines
35 */
36#ifdef __GNUC__
37#define CONST			__attribute__ ((__const__))
38#else
39#define CONST			/**/
40#endif
41
42/* mask for checking overflow on long operations */
43#ifdef LONG64
44#define FI_MASK			0x4000000000000000L
45#define LONGSBITS		63
46#else
47#define FI_MASK			0x40000000L
48#define LONGSBITS		31
49#endif
50
51#define N_FIXNUM		1
52#define N_BIGNUM		2
53#define N_FLONUM		3
54#define N_FIXRATIO		4
55#define N_BIGRATIO		5
56
57#define NOP_ADD			1
58#define NOP_SUB			2
59#define NOP_MUL			3
60#define NOP_DIV			4
61
62#define NDIVIDE_CEIL		1
63#define NDIVIDE_FLOOR		2
64#define NDIVIDE_ROUND		3
65#define NDIVIDE_TRUNC		4
66
67/* real part from number */
68#define NREAL(num)		&((num)->real)
69#define NRTYPE(num)		(num)->real.type
70#define NRFI(num)		(num)->real.data.fixnum
71#define NRBI(num)		(num)->real.data.bignum
72#define NRFF(num)		(num)->real.data.flonum
73#define NRFRN(Num)		(Num)->real.data.fixratio.num
74#define NRFRD(num)		(num)->real.data.fixratio.den
75#define NRBR(num)		(num)->real.data.bigratio
76#define NRBRN(num)		mpr_num(NRBR(num))
77#define NRBRD(num)		mpr_den(NRBR(num))
78
79#define NRCLEAR_BI(num)		mpi_clear(NRBI(num)); XFREE(NRBI(num))
80#define NRCLEAR_BR(num)		mpr_clear(NRBR(num)); XFREE(NRBR(num))
81
82/* imag part from number */
83#define NIMAG(num)		&((num)->imag)
84#define NITYPE(num)		(num)->imag.type
85#define NIFI(num)		(num)->imag.data.fixnum
86#define NIBI(num)		(num)->imag.data.bignum
87#define NIFF(num)		(num)->imag.data.flonum
88#define NIFRN(Num)		(Num)->imag.data.fixratio.num
89#define NIFRD(num)		(num)->imag.data.fixratio.den
90#define NIBR(num)		(num)->imag.data.bigratio
91#define NIBRN(obj)		mpr_num(NIBR(obj))
92#define NIBRD(obj)		mpr_den(NIBR(obj))
93
94/* real number fields */
95#define RTYPE(real)		(real)->type
96#define RFI(real)		(real)->data.fixnum
97#define RBI(real)		(real)->data.bignum
98#define RFF(real)		(real)->data.flonum
99#define RFRN(real)		(real)->data.fixratio.num
100#define RFRD(real)		(real)->data.fixratio.den
101#define RBR(real)		(real)->data.bigratio
102#define RBRN(real)		mpr_num(RBR(real))
103#define RBRD(real)		mpr_den(RBR(real))
104
105#define RINTEGERP(real)				\
106    (RTYPE(real) == N_FIXNUM || RTYPE(real) == N_BIGNUM)
107
108#define RCLEAR_BI(real)		mpi_clear(RBI(real)); XFREE(RBI(real))
109#define RCLEAR_BR(real)		mpr_clear(RBR(real)); XFREE(RBR(real))
110
111/* numeric value from lisp object */
112#define OFI(object)		FIXNUM_VALUE(object)
113#define OII(object)		INT_VALUE(object)
114#define OBI(object)		(object)->data.mp.integer
115#define ODF(object)		DFLOAT_VALUE(object)
116#define OFRN(object)		(object)->data.ratio.numerator
117#define OFRD(object)		(object)->data.ratio.denominator
118#define OBR(object)		(object)->data.mp.ratio
119#define OBRN(object)		mpr_num(OBR(object))
120#define OBRD(object)		mpr_den(OBR(object))
121#define OCXR(object)		(object)->data.complex.real
122#define OCXI(object)		(object)->data.complex.imag
123
124#define XALLOC(type)		LispMalloc(sizeof(type))
125#define XFREE(ptr)		LispFree(ptr)
126
127
128/*
129 * Types
130 */
131typedef struct _n_real {
132    char type;
133    union {
134	long fixnum;
135	mpi *bignum;
136	double flonum;
137	struct {
138	    long num;
139	    long den;
140	} fixratio;
141	mpr *bigratio;
142    } data;
143} n_real;
144
145typedef struct _n_number {
146    char complex;
147    n_real real;
148    n_real imag;
149} n_number;
150
151
152/*
153 * Prototypes
154 */
155static void number_init(void);
156static LispObj *number_pi(void);
157
158static void set_real_real(n_real*, n_real*);
159static void set_real_object(n_real*, LispObj*);
160static void set_number_object(n_number*, LispObj*);
161static void clear_real(n_real*);
162static void clear_number(n_number*);
163
164static LispObj *make_real_object(n_real*);
165static LispObj *make_number_object(n_number*);
166
167static void fatal_error(int);
168static void fatal_object_error(LispObj*, int);
169static void fatal_builtin_object_error(LispBuiltin*, LispObj*, int);
170
171static double bi_getd(mpi*);
172static double br_getd(mpr*);
173
174/* add */
175static void add_real_object(n_real*, LispObj*);
176static void add_number_object(n_number*, LispObj*);
177
178/* sub */
179static void sub_real_object(n_real*, LispObj*);
180static void sub_number_object(n_number*, LispObj*);
181
182/* mul */
183static void mul_real_object(n_real*, LispObj*);
184static void mul_number_object(n_number*, LispObj*);
185
186/* div */
187static void div_real_object(n_real*, LispObj*);
188static void div_number_object(n_number*, LispObj*);
189
190/* compare */
191static int cmp_real_real(n_real*, n_real*);
192static int cmp_real_object(n_real*, LispObj*);
193#if 0	/* not used */
194static int cmp_number_object(n_number*, LispObj*);
195#endif
196static int cmp_object_object(LispObj*, LispObj*, int);
197
198/* fixnum */
199static INLINE int fi_fi_add_overflow(long, long) CONST;
200static INLINE int fi_fi_sub_overflow(long, long) CONST;
201static INLINE int fi_fi_mul_overflow(long, long) CONST;
202
203/* bignum */
204static void rbi_canonicalize(n_real*);
205
206/* ratio */
207static void rfr_canonicalize(n_real*);
208static void rbr_canonicalize(n_real*);
209
210/* complex */
211static void ncx_canonicalize(n_number*);
212
213/* abs */
214static void abs_real(n_real*);
215static void abs_number(n_number*);
216static void nabs_cx(n_number*);
217static INLINE void rabs_fi(n_real*);
218static INLINE void rabs_bi(n_real*);
219static INLINE void rabs_ff(n_real*);
220static INLINE void rabs_fr(n_real*);
221static INLINE void rabs_br(n_real*);
222
223/* neg */
224static void neg_real(n_real*);
225static void neg_number(n_number*);
226static void rneg_fi(n_real*);
227static INLINE void rneg_bi(n_real*);
228static INLINE void rneg_ff(n_real*);
229static INLINE void rneg_fr(n_real*);
230static INLINE void rneg_br(n_real*);
231
232/* sqrt */
233static void sqrt_real(n_real*);
234static void sqrt_number(n_number*);
235static void rsqrt_xi(n_real*);
236static void rsqrt_xr(n_real*);
237static void rsqrt_ff(n_real*);
238static void nsqrt_cx(n_number*);
239static void nsqrt_xi(n_number*);
240static void nsqrt_ff(n_number*);
241static void nsqrt_xr(n_number*);
242
243/* mod */
244static void mod_real_real(n_real*, n_real*);
245static void mod_real_object(n_real*, LispObj*);
246static void rmod_fi_fi(n_real*, long);
247static void rmod_fi_bi(n_real*, mpi*);
248static void rmod_bi_fi(n_real*, long);
249static void rmod_bi_bi(n_real*, mpi*);
250
251/* rem */
252static void rem_real_object(n_real*, LispObj*);
253static void rrem_fi_fi(n_real*, long);
254static void rrem_fi_bi(n_real*, mpi*);
255static void rrem_bi_fi(n_real*, long);
256static void rrem_bi_bi(n_real*, mpi*);
257
258/* gcd */
259static void gcd_real_object(n_real*, LispObj*);
260
261/* and */
262static void and_real_object(n_real*, LispObj*);
263
264/* eqv */
265static void eqv_real_object(n_real*, LispObj*);
266
267/* ior */
268static void ior_real_object(n_real*, LispObj*);
269
270/* not */
271static void not_real(n_real*);
272
273/* xor */
274static void xor_real_object(n_real*, LispObj*);
275
276/* divide */
277static void divide_number_object(n_number*, LispObj*, int, int);
278static void ndivide_xi_xi(n_number*, LispObj*, int, int);
279static void ndivide_flonum(n_number*, double, double, int, int);
280static void ndivide_xi_xr(n_number*, LispObj*, int, int);
281static void ndivide_xr_xi(n_number*, LispObj*, int, int);
282static void ndivide_xr_xr(n_number*, LispObj*, int, int);
283
284/* real complex */
285static void nadd_re_cx(n_number*, LispObj*);
286static void nsub_re_cx(n_number*, LispObj*);
287static void nmul_re_cx(n_number*, LispObj*);
288static void ndiv_re_cx(n_number*, LispObj*);
289
290/* complex real */
291static void nadd_cx_re(n_number*, LispObj*);
292static void nsub_cx_re(n_number*, LispObj*);
293static void nmul_cx_re(n_number*, LispObj*);
294static void ndiv_cx_re(n_number*, LispObj*);
295
296/* complex complex */
297static void nadd_cx_cx(n_number*, LispObj*);
298static void nsub_cx_cx(n_number*, LispObj*);
299static void nmul_cx_cx(n_number*, LispObj*);
300static void ndiv_cx_cx(n_number*, LispObj*);
301static int cmp_cx_cx(LispObj*, LispObj*);
302
303/* flonum flonum */
304static void radd_flonum(n_real*, double, double);
305static void rsub_flonum(n_real*, double, double);
306static void rmul_flonum(n_real*, double, double);
307static void rdiv_flonum(n_real*, double, double);
308static int cmp_flonum(double, double);
309
310/* fixnum fixnum */
311static void rop_fi_fi_bi(n_real*, long, int);
312static INLINE void radd_fi_fi(n_real*, long);
313static INLINE void rsub_fi_fi(n_real*, long);
314static INLINE void rmul_fi_fi(n_real*, long);
315static INLINE void rdiv_fi_fi(n_real*, long);
316static INLINE int cmp_fi_fi(long, long);
317static void ndivide_fi_fi(n_number*, long, int, int);
318
319/* fixnum bignum */
320static void rop_fi_bi_xi(n_real*, mpi*, int);
321static INLINE void radd_fi_bi(n_real*, mpi*);
322static INLINE void rsub_fi_bi(n_real*, mpi*);
323static INLINE void rmul_fi_bi(n_real*, mpi*);
324static void rdiv_fi_bi(n_real*, mpi*);
325static INLINE int cmp_fi_bi(long, mpi*);
326
327/* fixnum fixratio */
328static void rop_fi_fr_as_xr(n_real*, long, long, int);
329static void rop_fi_fr_md_xr(n_real*, long, long, int);
330static INLINE void radd_fi_fr(n_real*, long, long);
331static INLINE void rsub_fi_fr(n_real*, long, long);
332static INLINE void rmul_fi_fr(n_real*, long, long);
333static INLINE void rdiv_fi_fr(n_real*, long, long);
334static INLINE int cmp_fi_fr(long, long, long);
335
336/* fixnum bigratio */
337static void rop_fi_br_as_xr(n_real*, mpr*, int);
338static void rop_fi_br_md_xr(n_real*, mpr*, int);
339static INLINE void radd_fi_br(n_real*, mpr*);
340static INLINE void rsub_fi_br(n_real*, mpr*);
341static INLINE void rmul_fi_br(n_real*, mpr*);
342static INLINE void rdiv_fi_br(n_real*, mpr*);
343static INLINE int cmp_fi_br(long, mpr*);
344
345/* bignum fixnum */
346static INLINE void radd_bi_fi(n_real*, long);
347static INLINE void rsub_bi_fi(n_real*, long);
348static INLINE void rmul_bi_fi(n_real*, long);
349static void rdiv_bi_fi(n_real*, long);
350static INLINE int cmp_bi_fi(mpi*, long);
351
352/* bignum bignum */
353static INLINE void radd_bi_bi(n_real*, mpi*);
354static INLINE void rsub_bi_bi(n_real*, mpi*);
355static INLINE void rmul_bi_bi(n_real*, mpi*);
356static void rdiv_bi_bi(n_real*, mpi*);
357static INLINE int cmp_bi_bi(mpi*, mpi*);
358
359/* bignum fixratio */
360static void rop_bi_fr_as_xr(n_real*, long, long, int);
361static void rop_bi_fr_md_xr(n_real*, long, long, int);
362static INLINE void radd_bi_fr(n_real*, long, long);
363static INLINE void rsub_bi_fr(n_real*, long, long);
364static INLINE void rmul_bi_fr(n_real*, long, long);
365static INLINE void rdiv_bi_fr(n_real*, long, long);
366static int cmp_bi_fr(mpi*, long, long);
367
368/* bignum bigratio */
369static void rop_bi_br_as_xr(n_real*, mpr*, int);
370static void rop_bi_br_md_xr(n_real*, mpr*, int);
371static INLINE void radd_bi_br(n_real*, mpr*);
372static INLINE void rsub_bi_br(n_real*, mpr*);
373static INLINE void rmul_bi_br(n_real*, mpr*);
374static INLINE void rdiv_bi_br(n_real*, mpr*);
375static int cmp_bi_br(mpi*, mpr*);
376
377/* fixratio fixnum */
378static void rop_fr_fi_as_xr(n_real*, long, int);
379static void rop_fr_fi_md_xr(n_real*, long, int);
380static INLINE void radd_fr_fi(n_real*, long);
381static INLINE void rsub_fr_fi(n_real*, long);
382static INLINE void rmul_fr_fi(n_real*, long);
383static INLINE void rdiv_fr_fi(n_real*, long);
384static INLINE int cmp_fr_fi(long, long, long);
385
386/* fixratio bignum */
387static void rop_fr_bi_as_xr(n_real*, mpi*, int);
388static void rop_fr_bi_md_xr(n_real*, mpi*, int);
389static INLINE void radd_fr_bi(n_real*, mpi*);
390static INLINE void rsub_fr_bi(n_real*, mpi*);
391static INLINE void rmul_fr_bi(n_real*, mpi*);
392static INLINE void rdiv_fr_bi(n_real*, mpi*);
393static int cmp_fr_bi(long, long, mpi*);
394
395/* fixratio fixratio */
396static void rop_fr_fr_as_xr(n_real*, long, long, int);
397static void rop_fr_fr_md_xr(n_real*, long, long, int);
398static INLINE void radd_fr_fr(n_real*, long, long);
399static INLINE void rsub_fr_fr(n_real*, long, long);
400static INLINE void rmul_fr_fr(n_real*, long, long);
401static INLINE void rdiv_fr_fr(n_real*, long, long);
402static INLINE int cmp_fr_fr(long, long, long, long);
403
404/* fixratio bigratio */
405static void rop_fr_br_asmd_xr(n_real*, mpr*, int);
406static INLINE void radd_fr_br(n_real*, mpr*);
407static INLINE void rsub_fr_br(n_real*, mpr*);
408static INLINE void rmul_fr_br(n_real*, mpr*);
409static INLINE void rdiv_fr_br(n_real*, mpr*);
410static int cmp_fr_br(long, long, mpr*);
411
412/* bigratio fixnum */
413static void rop_br_fi_asmd_xr(n_real*, long, int);
414static INLINE void radd_br_fi(n_real*, long);
415static INLINE void rsub_br_fi(n_real*, long);
416static INLINE void rmul_br_fi(n_real*, long);
417static INLINE void rdiv_br_fi(n_real*, long);
418static int cmp_br_fi(mpr*, long);
419
420/* bigratio bignum */
421static void rop_br_bi_as_xr(n_real*, mpi*, int);
422static INLINE void radd_br_bi(n_real*, mpi*);
423static INLINE void rsub_br_bi(n_real*, mpi*);
424static INLINE void rmul_br_bi(n_real*, mpi*);
425static INLINE void rdiv_br_bi(n_real*, mpi*);
426static int cmp_br_bi(mpr*, mpi*);
427
428/* bigratio fixratio */
429static void rop_br_fr_asmd_xr(n_real*, long, long, int);
430static INLINE void radd_br_fr(n_real*, long, long);
431static INLINE void rsub_br_fr(n_real*, long, long);
432static INLINE void rmul_br_fr(n_real*, long, long);
433static INLINE void rdiv_br_fr(n_real*, long, long);
434static int cmp_br_fr(mpr*, long, long);
435
436/* bigratio bigratio */
437static INLINE void radd_br_br(n_real*, mpr*);
438static INLINE void rsub_br_br(n_real*, mpr*);
439static INLINE void rmul_br_br(n_real*, mpr*);
440static INLINE void rdiv_br_br(n_real*, mpr*);
441static INLINE int cmp_br_br(mpr*, mpr*);
442
443/*
444 * Initialization
445 */
446static n_real zero, one, two;
447
448static char *fatal_error_strings[] = {
449#define DIVIDE_BY_ZERO			0
450    "divide by zero",
451#define FLOATING_POINT_OVERFLOW		1
452    "floating point overflow",
453#define FLOATING_POINT_EXCEPTION	2
454    "floating point exception"
455};
456
457static char *fatal_object_error_strings[] = {
458#define NOT_A_NUMBER			0
459    "is not a number",
460#define NOT_A_REAL_NUMBER		1
461    "is not a real number",
462#define NOT_AN_INTEGER			2
463    "is not an integer"
464};
465
466/*
467 * Implementation
468 */
469static void
470fatal_error(int num)
471{
472    LispDestroy(fatal_error_strings[num]);
473}
474
475static void
476fatal_object_error(LispObj *obj, int num)
477{
478    LispDestroy("%s %s", STROBJ(obj), fatal_object_error_strings[num]);
479}
480
481static void
482fatal_builtin_object_error(LispBuiltin *builtin, LispObj *obj, int num)
483{
484    LispDestroy("%s: %s %s", STRFUN(builtin), STROBJ(obj),
485		fatal_object_error_strings[num]);
486}
487
488static void
489number_init(void)
490{
491    zero.type = one.type = two.type = N_FIXNUM;
492    zero.data.fixnum = 0;
493    one.data.fixnum = 1;
494    two.data.fixnum = 2;
495}
496
497static double
498bi_getd(mpi *bignum)
499{
500    double value = mpi_getd(bignum);
501
502    if (!finite(value))
503	fatal_error(FLOATING_POINT_EXCEPTION);
504
505    return (value);
506}
507
508static double
509br_getd(mpr *bigratio)
510{
511    double value = mpr_getd(bigratio);
512
513    if (!finite(value))
514	fatal_error(FLOATING_POINT_EXCEPTION);
515
516    return (value);
517}
518
519static LispObj *
520number_pi(void)
521{
522    LispObj *result;
523#ifndef M_PI
524#define M_PI 3.14159265358979323846
525#endif
526    result = DFLOAT(M_PI);
527
528    return (result);
529}
530
531static void
532set_real_real(n_real *real, n_real *val)
533{
534    switch (RTYPE(real) = RTYPE(val)) {
535	case N_FIXNUM:
536	    RFI(real) = RFI(val);
537	    break;
538	case N_BIGNUM:
539	    RBI(real) = XALLOC(mpi);
540	    mpi_init(RBI(real));
541	    mpi_set(RBI(real), RBI(val));
542	    break;
543	case N_FLONUM:
544	    RFF(real) = RFF(val);
545	    break;
546	case N_FIXRATIO:
547	    RFRN(real) = RFRN(val);
548	    RFRD(real) = RFRD(val);
549	    break;
550	case N_BIGRATIO:
551	    RBR(real) = XALLOC(mpr);
552	    mpr_init(RBR(real));
553	    mpr_set(RBR(real), RBR(val));
554	    break;
555    }
556}
557
558static void
559set_real_object(n_real *real, LispObj *obj)
560{
561    switch (OBJECT_TYPE(obj)) {
562	case LispFixnum_t:
563	    RTYPE(real) = N_FIXNUM;
564	    RFI(real) = OFI(obj);
565	    break;
566	case LispInteger_t:
567	    RTYPE(real) = N_FIXNUM;
568	    RFI(real) = OII(obj);
569	    break;
570	case LispBignum_t:
571	    RTYPE(real) = N_BIGNUM;
572	    RBI(real) = XALLOC(mpi);
573	    mpi_init(RBI(real));
574	    mpi_set(RBI(real), OBI(obj));
575	    break;
576	case LispDFloat_t:
577	    RTYPE(real) = N_FLONUM;
578	    RFF(real) = ODF(obj);
579	    break;
580	case LispRatio_t:
581	    RTYPE(real) = N_FIXRATIO;
582	    RFRN(real) = OFRN(obj);
583	    RFRD(real) = OFRD(obj);
584	    break;
585	case LispBigratio_t:
586	    RTYPE(real) = N_BIGRATIO;
587	    RBR(real) = XALLOC(mpr);
588	    mpr_init(RBR(real));
589	    mpr_set(RBR(real), OBR(obj));
590	    break;
591	default:
592	    fatal_object_error(obj, NOT_A_REAL_NUMBER);
593	    break;
594    }
595}
596
597static void
598set_number_object(n_number *num, LispObj *obj)
599{
600    switch (OBJECT_TYPE(obj)) {
601	case LispFixnum_t:
602	    num->complex = 0;
603	    NRTYPE(num) = N_FIXNUM;
604	    NRFI(num) = OFI(obj);
605	    break;
606	case LispInteger_t:
607	    num->complex = 0;
608	    NRTYPE(num) = N_FIXNUM;
609	    NRFI(num) = OII(obj);
610	    break;
611	case LispBignum_t:
612	    num->complex = 0;
613	    NRTYPE(num) = N_BIGNUM;
614	    NRBI(num) = XALLOC(mpi);
615	    mpi_init(NRBI(num));
616	    mpi_set(NRBI(num), OBI(obj));
617	    break;
618	case LispDFloat_t:
619	    num->complex = 0;
620	    NRTYPE(num) = N_FLONUM;
621	    NRFF(num) = ODF(obj);
622	    break;
623	case LispRatio_t:
624	    num->complex = 0;
625	    NRTYPE(num) = N_FIXRATIO;
626	    NRFRN(num) = OFRN(obj);
627	    NRFRD(num) = OFRD(obj);
628	    break;
629	case LispBigratio_t:
630	    num->complex = 0;
631	    NRTYPE(num) = N_BIGRATIO;
632	    NRBR(num) = XALLOC(mpr);
633	    mpr_init(NRBR(num));
634	    mpr_set(NRBR(num), OBR(obj));
635	    break;
636	case LispComplex_t:
637	    num->complex = 1;
638	    set_real_object(NREAL(num), OCXR(obj));
639	    set_real_object(NIMAG(num), OCXI(obj));
640	    break;
641	default:
642	    fatal_object_error(obj, NOT_A_NUMBER);
643	    break;
644    }
645}
646
647static void
648clear_real(n_real *real)
649{
650    if (RTYPE(real) == N_BIGNUM) {
651	mpi_clear(RBI(real));
652	XFREE(RBI(real));
653    }
654    else if (RTYPE(real) == N_BIGRATIO) {
655	mpr_clear(RBR(real));
656	XFREE(RBR(real));
657    }
658}
659
660static void
661clear_number(n_number *num)
662{
663    clear_real(NREAL(num));
664    if (num->complex)
665	clear_real(NIMAG(num));
666}
667
668static LispObj *
669make_real_object(n_real *real)
670{
671    LispObj *obj;
672
673    switch (RTYPE(real)) {
674	case N_FIXNUM:
675	    if (RFI(real) > MOST_POSITIVE_FIXNUM ||
676		RFI(real) < MOST_NEGATIVE_FIXNUM) {
677		obj = LispNew(NIL, NIL);
678		obj->type = LispInteger_t;
679		OII(obj) = RFI(real);
680	    }
681	    else
682		obj = FIXNUM(RFI(real));
683	    break;
684	case N_BIGNUM:
685	    obj = BIGNUM(RBI(real));
686	    break;
687	case N_FLONUM:
688	    obj = DFLOAT(RFF(real));
689	    break;
690	case N_FIXRATIO:
691	    obj = LispNew(NIL, NIL);
692	    obj->type = LispRatio_t;
693	    OFRN(obj) = RFRN(real);
694	    OFRD(obj) = RFRD(real);
695	    break;
696	case N_BIGRATIO:
697	    obj = BIGRATIO(RBR(real));
698	    break;
699	default:
700	    obj = NIL;
701	    break;
702    }
703
704    return (obj);
705}
706
707static LispObj *
708make_number_object(n_number *num)
709{
710    LispObj *obj;
711
712    if (num->complex) {
713	GC_ENTER();
714
715	obj = LispNew(NIL, NIL);
716	GC_PROTECT(obj);
717	OCXI(obj) = NIL;
718	obj->type = LispComplex_t;
719	OCXR(obj) = make_real_object(NREAL(num));
720	OCXI(obj) = make_real_object(NIMAG(num));
721	GC_LEAVE();
722    }
723    else {
724	switch (NRTYPE(num)) {
725	    case N_FIXNUM:
726		if (NRFI(num) > MOST_POSITIVE_FIXNUM ||
727		    NRFI(num) < MOST_NEGATIVE_FIXNUM) {
728		    obj = LispNew(NIL, NIL);
729		    obj->type = LispInteger_t;
730		    OII(obj) = NRFI(num);
731		}
732		else
733		    obj = FIXNUM(NRFI(num));
734		break;
735	    case N_BIGNUM:
736		obj = BIGNUM(NRBI(num));
737		break;
738	    case N_FLONUM:
739		obj = DFLOAT(NRFF(num));
740		break;
741	    case N_FIXRATIO:
742		obj = LispNew(NIL, NIL);
743		obj->type = LispRatio_t;
744		OFRN(obj) = NRFRN(num);
745		OFRD(obj) = NRFRD(num);
746		break;
747	    case N_BIGRATIO:
748		obj = BIGRATIO(NRBR(num));
749		break;
750	    default:
751		obj = NIL;
752		break;
753	}
754    }
755
756    return (obj);
757}
758
759#define DEFOP_REAL_REAL(OP)						\
760OP##_real_real(n_real *real, n_real *val)				\
761{									\
762    switch (RTYPE(real)) {						\
763	case N_FIXNUM:							\
764	    switch (RTYPE(val)) {					\
765		case N_FIXNUM:						\
766		    r##OP##_fi_fi(real, RFI(val));			\
767		    break;						\
768		case N_BIGNUM:						\
769		    r##OP##_fi_bi(real, RBI(val));			\
770		    break;						\
771		case N_FLONUM:						\
772		    r##OP##_flonum(real, (double)RFI(real), RFF(val));	\
773		    break;						\
774		case N_FIXRATIO:					\
775		    r##OP##_fi_fr(real, RFRN(val), RFRD(val));		\
776		    break;						\
777		case N_BIGRATIO:					\
778		    r##OP##_fi_br(real, RBR(val));			\
779		    break;						\
780	    }								\
781	    break;							\
782	case N_BIGNUM:							\
783	    switch (RTYPE(val)) {					\
784		case N_FIXNUM:						\
785		    r##OP##_bi_fi(real, RFI(val));			\
786		    break;						\
787		case N_BIGNUM:						\
788		    r##OP##_bi_bi(real, RBI(val));			\
789		    break;						\
790		case N_FLONUM:						\
791		    r##OP##_flonum(real, bi_getd(RBI(real)), RFF(val));	\
792		    break;						\
793		case N_FIXRATIO:					\
794		    r##OP##_bi_fr(real, RFRN(val), RFRD(val));		\
795		    break;						\
796		case N_BIGRATIO:					\
797		    r##OP##_bi_br(real, RBR(val));			\
798		    break;						\
799	    }								\
800	    break;							\
801	case N_FLONUM:							\
802	    switch (RTYPE(val)) {					\
803		case N_FIXNUM:						\
804		    r##OP##_flonum(real, RFF(real), (double)RFI(val));	\
805		    break;						\
806		case N_BIGNUM:						\
807		    r##OP##_flonum(real, RFF(real), bi_getd(RBI(val)));	\
808		    break;						\
809		case N_FLONUM:						\
810		    r##OP##_flonum(real, RFF(real), RFF(val));		\
811		    break;						\
812		case N_FIXRATIO:					\
813		    r##OP##_flonum(real, RFF(real),			\
814				 (double)RFRN(val) / (double)RFRD(val));\
815		    break;						\
816		case N_BIGRATIO:					\
817		    r##OP##_flonum(real, RFF(real), br_getd(RBR(val)));	\
818		    break;						\
819	    }								\
820	    break;							\
821	case N_FIXRATIO:						\
822	    switch (RTYPE(val)) {					\
823		case N_FIXNUM:						\
824		    r##OP##_fr_fi(real, RFI(val));			\
825		    break;						\
826		case N_BIGNUM:						\
827		    r##OP##_fr_bi(real, RBI(val));			\
828		    break;						\
829		case N_FLONUM:						\
830		    r##OP##_flonum(real,				\
831				(double)RFRN(real) / (double)RFRD(real),\
832				RFF(val));				\
833		    break;						\
834		case N_FIXRATIO:					\
835		    r##OP##_fr_fr(real, RFRN(val), RFRD(val));		\
836		    break;						\
837		case N_BIGRATIO:					\
838		    r##OP##_fr_br(real, RBR(val));			\
839		    break;						\
840	    }								\
841	    break;							\
842	case N_BIGRATIO:						\
843	    switch (RTYPE(val)) {					\
844		case N_FIXNUM:						\
845		    r##OP##_br_fi(real, RFI(val));			\
846		    break;						\
847		case N_BIGNUM:						\
848		    r##OP##_br_bi(real, RBI(val));			\
849		    break;						\
850		case N_FLONUM:						\
851		    r##OP##_flonum(real, br_getd(RBR(real)), RFF(val));	\
852		    break;						\
853		case N_FIXRATIO:					\
854		    r##OP##_br_fr(real, RFRN(val), RFRD(val));		\
855		    break;						\
856		case N_BIGRATIO:					\
857		    r##OP##_br_br(real, RBR(val));			\
858		    break;						\
859	    }								\
860	    break;							\
861    }									\
862}
863
864static void
865DEFOP_REAL_REAL(add)
866
867static void
868DEFOP_REAL_REAL(sub)
869
870static void
871DEFOP_REAL_REAL(div)
872
873static void
874DEFOP_REAL_REAL(mul)
875
876
877#define DEFOP_REAL_OBJECT(OP)						\
878OP##_real_object(n_real *real, LispObj *obj)				\
879{									\
880    switch (OBJECT_TYPE(obj)) {						\
881	case LispFixnum_t:						\
882	    switch (RTYPE(real)) {					\
883		case N_FIXNUM:						\
884		    r##OP##_fi_fi(real, OFI(obj));			\
885		    break;						\
886		case N_BIGNUM:						\
887		    r##OP##_bi_fi(real, OFI(obj));			\
888		    break;						\
889		case N_FLONUM:						\
890		    r##OP##_flonum(real, RFF(real), (double)OFI(obj));	\
891		    break;						\
892		case N_FIXRATIO:					\
893		    r##OP##_fr_fi(real, OFI(obj));			\
894		    break;						\
895		case N_BIGRATIO:					\
896		    r##OP##_br_fi(real, OFI(obj));			\
897		    break;						\
898	    }								\
899	    break;							\
900	case LispInteger_t:						\
901	    switch (RTYPE(real)) {					\
902		case N_FIXNUM:						\
903		    r##OP##_fi_fi(real, OII(obj));			\
904		    break;						\
905		case N_BIGNUM:						\
906		    r##OP##_bi_fi(real, OII(obj));			\
907		    break;						\
908		case N_FLONUM:						\
909		    r##OP##_flonum(real, RFF(real), (double)OII(obj));	\
910		    break;						\
911		case N_FIXRATIO:					\
912		    r##OP##_fr_fi(real, OII(obj));			\
913		    break;						\
914		case N_BIGRATIO:					\
915		    r##OP##_br_fi(real, OII(obj));			\
916		    break;						\
917	    }								\
918	    break;							\
919	case LispBignum_t:						\
920	    switch (RTYPE(real)) {					\
921		case N_FIXNUM:						\
922		    r##OP##_fi_bi(real, OBI(obj));			\
923		    break;						\
924		case N_BIGNUM:						\
925		    r##OP##_bi_bi(real, OBI(obj));			\
926		    break;						\
927		case N_FLONUM:						\
928		    r##OP##_flonum(real, RFF(real), bi_getd(OBI(obj)));	\
929		    break;						\
930		case N_FIXRATIO:					\
931		    r##OP##_fr_bi(real, OBI(obj));			\
932		    break;						\
933		case N_BIGRATIO:					\
934		    r##OP##_br_bi(real, OBI(obj));			\
935		    break;						\
936	    }								\
937	    break;							\
938	case LispDFloat_t:						\
939	    switch (RTYPE(real)) {					\
940		case N_FIXNUM:						\
941		    r##OP##_flonum(real, (double)RFI(real), ODF(obj));	\
942		    break;						\
943		case N_BIGNUM:						\
944		    r##OP##_flonum(real, bi_getd(RBI(real)), ODF(obj));	\
945		    break;						\
946		case N_FLONUM:						\
947		    r##OP##_flonum(real, RFF(real), ODF(obj));		\
948		    break;						\
949		case N_FIXRATIO:					\
950		    r##OP##_flonum(real,				\
951				(double)RFRN(real) / (double)RFRD(real),\
952				ODF(obj));				\
953		    break;						\
954		case N_BIGRATIO:					\
955		    r##OP##_flonum(real, br_getd(RBR(real)), ODF(obj));	\
956		    break;						\
957	    }								\
958	    break;							\
959	case LispRatio_t:						\
960	    switch (RTYPE(real)) {					\
961		case N_FIXNUM:						\
962		    r##OP##_fi_fr(real, OFRN(obj), OFRD(obj));		\
963		    break;						\
964		case N_BIGNUM:						\
965		    r##OP##_bi_fr(real, OFRN(obj), OFRD(obj));		\
966		    break;						\
967		case N_FLONUM:						\
968		    r##OP##_flonum(real, RFF(real),			\
969				(double)OFRN(obj) / (double)OFRD(obj));	\
970		    break;						\
971		case N_FIXRATIO:					\
972		    r##OP##_fr_fr(real, OFRN(obj), OFRD(obj));		\
973		    break;						\
974		case N_BIGRATIO:					\
975		    r##OP##_br_fr(real, OFRN(obj), OFRD(obj));		\
976		    break;						\
977	    }								\
978	    break;							\
979	case LispBigratio_t:						\
980	    switch (RTYPE(real)) {					\
981		case N_FIXNUM:						\
982		    r##OP##_fi_br(real, OBR(obj));			\
983		    break;						\
984		case N_BIGNUM:						\
985		    r##OP##_bi_br(real, OBR(obj));			\
986		    break;						\
987		case N_FLONUM:						\
988		    r##OP##_flonum(real, RFF(real), br_getd(OBR(obj)));	\
989		    break;						\
990		case N_FIXRATIO:					\
991		    r##OP##_fr_br(real, OBR(obj));			\
992		    break;						\
993		case N_BIGRATIO:					\
994		    r##OP##_br_br(real, OBR(obj));			\
995		    break;						\
996	    }								\
997	    break;							\
998	default:							\
999	    fatal_object_error(obj, NOT_A_REAL_NUMBER);			\
1000	    break;							\
1001    }									\
1002}
1003
1004static void
1005DEFOP_REAL_OBJECT(add)
1006
1007static void
1008DEFOP_REAL_OBJECT(sub)
1009
1010static void
1011DEFOP_REAL_OBJECT(div)
1012
1013static void
1014DEFOP_REAL_OBJECT(mul)
1015
1016
1017#define DEFOP_NUMBER_OBJECT(OP)						\
1018OP##_number_object(n_number *num, LispObj *obj)				\
1019{									\
1020    if (num->complex) {							\
1021	switch (OBJECT_TYPE(obj)) {					\
1022	    case LispFixnum_t:						\
1023	    case LispInteger_t:						\
1024	    case LispBignum_t:						\
1025	    case LispDFloat_t:						\
1026	    case LispRatio_t:						\
1027	    case LispBigratio_t:					\
1028		n##OP##_cx_re(num, obj);				\
1029		break;							\
1030	    case LispComplex_t:						\
1031		n##OP##_cx_cx(num, obj);				\
1032		break;							\
1033	    default:							\
1034		fatal_object_error(obj, NOT_A_NUMBER);			\
1035		break;							\
1036	}								\
1037    }									\
1038    else {								\
1039	switch (OBJECT_TYPE(obj)) {					\
1040	    case LispFixnum_t:						\
1041		switch (NRTYPE(num)) {					\
1042		    case N_FIXNUM:					\
1043			r##OP##_fi_fi(NREAL(num), OFI(obj));		\
1044			break;						\
1045		    case N_BIGNUM:					\
1046			r##OP##_bi_fi(NREAL(num), OFI(obj));		\
1047			break;						\
1048		    case N_FLONUM:					\
1049			r##OP##_flonum(NREAL(num), NRFF(num),		\
1050				    (double)OFI(obj));			\
1051			break;						\
1052		    case N_FIXRATIO:					\
1053			r##OP##_fr_fi(NREAL(num), OFI(obj));		\
1054			break;						\
1055		    case N_BIGRATIO:					\
1056			r##OP##_br_fi(NREAL(num), OFI(obj));		\
1057			break;						\
1058		}							\
1059		break;							\
1060	    case LispInteger_t:						\
1061		switch (NRTYPE(num)) {					\
1062		    case N_FIXNUM:					\
1063			r##OP##_fi_fi(NREAL(num), OII(obj));		\
1064			break;						\
1065		    case N_BIGNUM:					\
1066			r##OP##_bi_fi(NREAL(num), OII(obj));		\
1067			break;						\
1068		    case N_FLONUM:					\
1069			r##OP##_flonum(NREAL(num), NRFF(num),		\
1070				    (double)OII(obj));			\
1071			break;						\
1072		    case N_FIXRATIO:					\
1073			r##OP##_fr_fi(NREAL(num), OII(obj));		\
1074			break;						\
1075		    case N_BIGRATIO:					\
1076			r##OP##_br_fi(NREAL(num), OII(obj));		\
1077			break;						\
1078		}							\
1079		break;							\
1080	    case LispBignum_t:						\
1081		switch (NRTYPE(num)) {					\
1082		    case N_FIXNUM:					\
1083			r##OP##_fi_bi(NREAL(num), OBI(obj));		\
1084			break;						\
1085		    case N_BIGNUM:					\
1086			r##OP##_bi_bi(NREAL(num), OBI(obj));		\
1087			break;						\
1088		    case N_FLONUM:					\
1089			r##OP##_flonum(NREAL(num), NRFF(num),		\
1090				       bi_getd(OBI(obj)));		\
1091			break;						\
1092		    case N_FIXRATIO:					\
1093			r##OP##_fr_bi(NREAL(num), OBI(obj));		\
1094			break;						\
1095		    case N_BIGRATIO:					\
1096			r##OP##_br_bi(NREAL(num), OBI(obj));		\
1097			break;						\
1098		}							\
1099		break;							\
1100	    case LispDFloat_t:						\
1101		switch (NRTYPE(num)) {					\
1102		    case N_FIXNUM:					\
1103			r##OP##_flonum(NREAL(num), (double)NRFI(num),	\
1104				    ODF(obj));				\
1105			break;						\
1106		    case N_BIGNUM:					\
1107			r##OP##_flonum(NREAL(num), bi_getd(NRBI(num)),	\
1108				    ODF(obj));				\
1109			break;						\
1110		    case N_FLONUM:					\
1111			r##OP##_flonum(NREAL(num), NRFF(num), ODF(obj));\
1112			break;						\
1113		    case N_FIXRATIO:					\
1114			r##OP##_flonum(NREAL(num),			\
1115				    (double)NRFRN(num) /		\
1116				    (double)NRFRD(num),			\
1117				    ODF(obj));				\
1118			break;						\
1119		    case N_BIGRATIO:					\
1120			r##OP##_flonum(NREAL(num), br_getd(NRBR(num)),	\
1121				    ODF(obj));				\
1122			break;						\
1123		}							\
1124		break;							\
1125	    case LispRatio_t:						\
1126		switch (NRTYPE(num)) {					\
1127		    case N_FIXNUM:					\
1128			r##OP##_fi_fr(NREAL(num), OFRN(obj), OFRD(obj));\
1129			break;						\
1130		    case N_BIGNUM:					\
1131			r##OP##_bi_fr(NREAL(num), OFRN(obj), OFRD(obj));\
1132			break;						\
1133		    case N_FLONUM:					\
1134			r##OP##_flonum(NREAL(num), NRFF(num),		\
1135				    (double)OFRN(obj) /			\
1136				    (double)OFRD(obj));			\
1137			break;						\
1138		    case N_FIXRATIO:					\
1139			r##OP##_fr_fr(NREAL(num), OFRN(obj), OFRD(obj));\
1140			break;						\
1141		    case N_BIGRATIO:					\
1142			r##OP##_br_fr(NREAL(num), OFRN(obj), OFRD(obj));\
1143			break;						\
1144		}							\
1145		break;							\
1146	    case LispBigratio_t:					\
1147		switch (NRTYPE(num)) {					\
1148		    case N_FIXNUM:					\
1149			r##OP##_fi_br(NREAL(num), OBR(obj));		\
1150			break;						\
1151		    case N_BIGNUM:					\
1152			r##OP##_bi_br(NREAL(num), OBR(obj));		\
1153			break;						\
1154		    case N_FLONUM:					\
1155			r##OP##_flonum(NREAL(num), NRFF(num),		\
1156				    br_getd(OBR(obj)));		\
1157			break;						\
1158		    case N_FIXRATIO:					\
1159			r##OP##_fr_br(NREAL(num), OBR(obj));		\
1160			break;						\
1161		    case N_BIGRATIO:					\
1162			r##OP##_br_br(NREAL(num), OBR(obj));		\
1163			break;						\
1164		}							\
1165		break;							\
1166	    case LispComplex_t:						\
1167		n##OP##_re_cx(num, obj);				\
1168		break;							\
1169	    default:							\
1170		fatal_object_error(obj, NOT_A_NUMBER);			\
1171		break;							\
1172	}								\
1173    }									\
1174}
1175
1176static void
1177DEFOP_NUMBER_OBJECT(add)
1178
1179static void
1180DEFOP_NUMBER_OBJECT(sub)
1181
1182static void
1183DEFOP_NUMBER_OBJECT(div)
1184
1185static void
1186DEFOP_NUMBER_OBJECT(mul)
1187
1188
1189/************************************************************************
1190 * ABS
1191 ************************************************************************/
1192static void
1193abs_real(n_real *real)
1194{
1195    switch (RTYPE(real)) {
1196	case N_FIXNUM:		rabs_fi(real);	break;
1197	case N_BIGNUM:		rabs_bi(real);	break;
1198	case N_FLONUM:		rabs_ff(real);	break;
1199	case N_FIXRATIO:	rabs_fr(real);	break;
1200	case N_BIGRATIO:	rabs_br(real);	break;
1201    }
1202}
1203
1204static void
1205abs_number(n_number *num)
1206{
1207    if (num->complex)
1208	nabs_cx(num);
1209    else {
1210	switch (NRTYPE(num)) {
1211	    case N_FIXNUM:	rabs_fi(NREAL(num));	break;
1212	    case N_BIGNUM:	rabs_bi(NREAL(num));	break;
1213	    case N_FLONUM:	rabs_ff(NREAL(num));	break;
1214	    case N_FIXRATIO:	rabs_fr(NREAL(num));	break;
1215	    case N_BIGRATIO:	rabs_br(NREAL(num));	break;
1216	}
1217    }
1218}
1219
1220static void
1221nabs_cx(n_number *num)
1222{
1223    n_real temp;
1224
1225    abs_real(NREAL(num));
1226    abs_real(NIMAG(num));
1227
1228    if (cmp_real_real(NREAL(num), NIMAG(num)) < 0) {
1229	memcpy(&temp, NIMAG(num), sizeof(n_real));
1230	memcpy(NIMAG(num), NREAL(num), sizeof(n_real));
1231	memcpy(NREAL(num), &temp, sizeof(n_real));
1232    }
1233
1234    if (cmp_real_real(NIMAG(num), &zero) == 0) {
1235	num->complex = 0;
1236	if (NITYPE(num) == N_FLONUM) {
1237	    /* change number type */
1238	    temp.type = N_FLONUM;
1239	    temp.data.flonum = 1.0;
1240	    mul_real_real(NREAL(num), &temp);
1241	}
1242	else
1243	    clear_real(NIMAG(num));
1244    }
1245    else {
1246	div_real_real(NIMAG(num), NREAL(num));
1247	set_real_real(&temp, NIMAG(num));
1248	mul_real_real(NIMAG(num), &temp);
1249	clear_real(&temp);
1250
1251	add_real_real(NIMAG(num), &one);
1252	sqrt_real(NIMAG(num));
1253
1254	mul_real_real(NIMAG(num), NREAL(num));
1255	clear_real(NREAL(num));
1256	memcpy(NREAL(num), NIMAG(num), sizeof(n_real));
1257	num->complex = 0;
1258    }
1259}
1260
1261static INLINE void
1262rabs_fi(n_real *real)
1263{
1264    if (RFI(real) < 0)
1265	rneg_fi(real);
1266}
1267
1268static INLINE void
1269rabs_bi(n_real *real)
1270{
1271    if (mpi_cmpi(RBI(real), 0) < 0)
1272	mpi_neg(RBI(real), RBI(real));
1273}
1274
1275static INLINE void
1276rabs_ff(n_real *real)
1277{
1278    if (RFF(real) < 0.0)
1279	RFF(real) = -RFF(real);
1280}
1281
1282static INLINE void
1283rabs_fr(n_real *real)
1284{
1285    if (RFRN(real) < 0)
1286	rneg_fr(real);
1287}
1288
1289static INLINE void
1290rabs_br(n_real *real)
1291{
1292    if (mpi_cmpi(RBRN(real), 0) < 0)
1293	mpi_neg(RBRN(real), RBRN(real));
1294}
1295
1296
1297/************************************************************************
1298 * NEG
1299 ************************************************************************/
1300static void
1301neg_real(n_real *real)
1302{
1303    switch (RTYPE(real)) {
1304	case N_FIXNUM:		rneg_fi(real);	break;
1305	case N_BIGNUM:		rneg_bi(real);	break;
1306	case N_FLONUM:		rneg_ff(real);	break;
1307	case N_FIXRATIO:	rneg_fr(real);	break;
1308	case N_BIGRATIO:	rneg_br(real);	break;
1309    }
1310}
1311
1312static void
1313neg_number(n_number *num)
1314{
1315    if (num->complex) {
1316	neg_real(NREAL(num));
1317	neg_real(NIMAG(num));
1318    }
1319    else {
1320	switch (NRTYPE(num)) {
1321	    case N_FIXNUM:	rneg_fi(NREAL(num));	break;
1322	    case N_BIGNUM:	rneg_bi(NREAL(num));	break;
1323	    case N_FLONUM:	rneg_ff(NREAL(num));	break;
1324	    case N_FIXRATIO:	rneg_fr(NREAL(num));	break;
1325	    case N_BIGRATIO:	rneg_br(NREAL(num));	break;
1326	}
1327    }
1328}
1329
1330static void
1331rneg_fi(n_real *real)
1332{
1333    if (RFI(real) == MINSLONG) {
1334	mpi *bigi = XALLOC(mpi);
1335
1336	mpi_init(bigi);
1337	mpi_seti(bigi, RFI(real));
1338	mpi_neg(bigi, bigi);
1339	RTYPE(real) = N_BIGNUM;
1340	RBI(real) = bigi;
1341    }
1342    else
1343	RFI(real) = -RFI(real);
1344}
1345
1346static INLINE void
1347rneg_bi(n_real *real)
1348{
1349    mpi_neg(RBI(real), RBI(real));
1350}
1351
1352static INLINE void
1353rneg_ff(n_real *real)
1354{
1355    RFF(real) = -RFF(real);
1356}
1357
1358static void
1359rneg_fr(n_real *real)
1360{
1361    if (RFRN(real) == MINSLONG) {
1362	mpr *bigr = XALLOC(mpr);
1363
1364	mpr_init(bigr);
1365	mpr_seti(bigr, RFRN(real), RFRD(real));
1366	mpi_neg(mpr_num(bigr), mpr_num(bigr));
1367	RTYPE(real) = N_BIGRATIO;
1368	RBR(real) = bigr;
1369    }
1370    else
1371	RFRN(real) = -RFRN(real);
1372}
1373
1374static INLINE void
1375rneg_br(n_real *real)
1376{
1377    mpi_neg(RBRN(real), RBRN(real));
1378}
1379
1380
1381/************************************************************************
1382 * SQRT
1383 ************************************************************************/
1384static void
1385sqrt_real(n_real *real)
1386{
1387    switch (RTYPE(real)) {
1388	case N_FIXNUM:
1389	case N_BIGNUM:
1390	    rsqrt_xi(real);
1391	    break;
1392	case N_FLONUM:
1393	    rsqrt_ff(real);
1394	    break;
1395	case N_FIXRATIO:
1396	case N_BIGRATIO:
1397	    rsqrt_xr(real);
1398	    break;
1399    }
1400}
1401
1402static void
1403sqrt_number(n_number *num)
1404{
1405    if (num->complex)
1406	nsqrt_cx(num);
1407    else {
1408	switch (NRTYPE(num)) {
1409	    case N_FIXNUM:
1410	    case N_BIGNUM:
1411		nsqrt_xi(num);
1412		break;
1413	    case N_FLONUM:
1414		nsqrt_ff(num);
1415		break;
1416	    case N_FIXRATIO:
1417	    case N_BIGRATIO:
1418		nsqrt_xr(num);
1419		break;
1420	}
1421    }
1422}
1423
1424static void
1425rsqrt_xi(n_real *real)
1426{
1427    int exact;
1428    mpi bignum;
1429
1430    if (cmp_real_real(real, &zero) < 0)
1431	fatal_error(FLOATING_POINT_EXCEPTION);
1432
1433    mpi_init(&bignum);
1434    if (RTYPE(real) == N_BIGNUM)
1435	exact = mpi_sqrt(&bignum, RBI(real));
1436    else {
1437	mpi tmp;
1438
1439	mpi_init(&tmp);
1440	mpi_seti(&tmp, RFI(real));
1441	exact = mpi_sqrt(&bignum, &tmp);
1442	mpi_clear(&tmp);
1443    }
1444    if (exact) {
1445	if (RTYPE(real) == N_BIGNUM) {
1446	    mpi_set(RBI(real), &bignum);
1447	    rbi_canonicalize(real);
1448	}
1449	else
1450	    RFI(real) = mpi_geti(&bignum);
1451    }
1452    else {
1453	double value;
1454
1455	if (RTYPE(real) == N_BIGNUM) {
1456	    value = bi_getd(RBI(real));
1457	    RCLEAR_BI(real);
1458	}
1459	else
1460	    value = (double)RFI(real);
1461
1462	value = sqrt(value);
1463	RTYPE(real) = N_FLONUM;
1464	RFF(real) = value;
1465    }
1466    mpi_clear(&bignum);
1467}
1468
1469static void
1470rsqrt_xr(n_real *real)
1471{
1472    n_real num, den;
1473
1474    if (cmp_real_real(real, &zero) < 0)
1475	fatal_error(FLOATING_POINT_EXCEPTION);
1476
1477    if (RTYPE(real) == N_FIXRATIO) {
1478	num.type = den.type = N_FIXNUM;
1479	num.data.fixnum = RFRN(real);
1480	den.data.fixnum = RFRD(real);
1481    }
1482    else {
1483	mpi *bignum;
1484
1485	if (mpi_fiti(RBRN(real))) {
1486	    num.type = N_FIXNUM;
1487	    num.data.fixnum = mpi_geti(RBRN(real));
1488	}
1489	else {
1490	    bignum = XALLOC(mpi);
1491	    mpi_init(bignum);
1492	    mpi_set(bignum, RBRN(real));
1493	    num.type = N_BIGNUM;
1494	    num.data.bignum = bignum;
1495	}
1496
1497	if (mpi_fiti(RBRD(real))) {
1498	    den.type = N_FIXNUM;
1499	    den.data.fixnum = mpi_geti(RBRD(real));
1500	}
1501	else {
1502	    bignum = XALLOC(mpi);
1503	    mpi_init(bignum);
1504	    mpi_set(bignum, RBRD(real));
1505	    den.type = N_BIGNUM;
1506	    den.data.bignum = bignum;
1507	}
1508    }
1509
1510    rsqrt_xi(&num);
1511    rsqrt_xi(&den);
1512
1513    clear_real(real);
1514    memcpy(real, &num, sizeof(n_real));
1515    div_real_real(real, &den);
1516    clear_real(&den);
1517}
1518
1519static void
1520rsqrt_ff(n_real *real)
1521{
1522    if (RFF(real) < 0.0)
1523	fatal_error(FLOATING_POINT_EXCEPTION);
1524    RFF(real) = sqrt(RFF(real));
1525}
1526
1527
1528static void
1529nsqrt_cx(n_number *num)
1530{
1531    n_number mag;
1532    n_real *real, *imag;
1533
1534    real = &(mag.real);
1535    imag = &(mag.imag);
1536    set_real_real(real, NREAL(num));
1537    set_real_real(imag, NIMAG(num));
1538    mag.complex = 1;
1539
1540    nabs_cx(&mag);	/* this will free the imag part data */
1541    if (cmp_real_real(real, &zero) == 0) {
1542	clear_number(num);
1543	memcpy(NREAL(num), real, sizeof(n_real));
1544	clear_real(real);
1545	num->complex = 0;
1546	return;
1547    }
1548    else if (cmp_real_real(NREAL(num), &zero) > 0) {
1549	/* R = sqrt((mag + Ra) / 2) */
1550	add_real_real(NREAL(num), real);
1551	clear_real(real);
1552	div_real_real(NREAL(num), &two);
1553	sqrt_real(NREAL(num));
1554
1555	/* I = Ia / R / 2 */
1556	div_real_real(NIMAG(num), NREAL(num));
1557	div_real_real(NIMAG(num), &two);
1558    }
1559    else {
1560	/* remember old imag part */
1561	memcpy(imag, NIMAG(num), sizeof(n_real));
1562
1563	/* I = sqrt((mag - Ra) / 2) */
1564	memcpy(NIMAG(num), real, sizeof(n_real));
1565	sub_real_real(NIMAG(num), NREAL(num));
1566	div_real_real(NIMAG(num), &two);
1567	sqrt_real(NIMAG(num));
1568	if (cmp_real_real(imag, &zero) < 0)
1569	    neg_real(NIMAG(num));
1570
1571	/* R = Ia / I / 2 */
1572	clear_real(NREAL(num));
1573	/* start with old imag part */
1574	memcpy(NREAL(num), imag, sizeof(n_real));
1575	div_real_real(NREAL(num), NIMAG(num));
1576	div_real_real(NREAL(num), &two);
1577    }
1578
1579    ncx_canonicalize(num);
1580}
1581
1582static void
1583nsqrt_xi(n_number *num)
1584{
1585    if (cmp_real_real(NREAL(num), &zero) < 0) {
1586	memcpy(NIMAG(num), NREAL(num), sizeof(n_real));
1587	neg_real(NIMAG(num));
1588	rsqrt_xi(NIMAG(num));
1589	NRTYPE(num) = N_FIXNUM;
1590	NRFI(num) = 0;
1591	num->complex = 1;
1592    }
1593    else
1594	rsqrt_xi(NREAL(num));
1595}
1596
1597static void
1598nsqrt_ff(n_number *num)
1599{
1600    double value;
1601
1602    if (NRFF(num) < 0.0) {
1603	value = sqrt(-NRFF(num));
1604
1605	NITYPE(num) = N_FLONUM;
1606	NIFF(num) = value;
1607	NRTYPE(num) = N_FIXNUM;
1608	NRFI(num) = 0;
1609	num->complex = 1;
1610    }
1611    else {
1612	value = sqrt(NRFF(num));
1613	NRFF(num) = value;
1614    }
1615}
1616
1617static void
1618nsqrt_xr(n_number *num)
1619{
1620    if (cmp_real_real(NREAL(num), &zero) < 0) {
1621	memcpy(NIMAG(num), NREAL(num), sizeof(n_real));
1622	neg_real(NIMAG(num));
1623	rsqrt_xr(NIMAG(num));
1624	NRTYPE(num) = N_FIXNUM;
1625	NRFI(num) = 0;
1626	num->complex = 1;
1627    }
1628    else
1629	rsqrt_xr(NREAL(num));
1630}
1631
1632
1633/************************************************************************
1634 * MOD
1635 ************************************************************************/
1636static void
1637mod_real_real(n_real *real, n_real *val)
1638{
1639    /* Assume both operands are integers */
1640    switch (RTYPE(real)) {
1641	case N_FIXNUM:
1642	    switch (RTYPE(val)) {
1643		case N_FIXNUM:
1644		    rmod_fi_fi(real, RFI(val));
1645		    break;
1646		case N_BIGNUM:
1647		    rmod_fi_bi(real, RBI(val));
1648		    break;
1649	    }
1650	    break;
1651	case N_BIGNUM:
1652	    switch (RTYPE(val)) {
1653		case N_FIXNUM:
1654		    rmod_bi_fi(real, RFI(val));
1655		    break;
1656		case N_BIGNUM:
1657		    rmod_bi_bi(real, RBI(val));
1658		    break;
1659	    }
1660	    break;
1661    }
1662}
1663
1664static void
1665mod_real_object(n_real *real, LispObj *obj)
1666{
1667    switch (RTYPE(real)) {
1668	case N_FIXNUM:
1669	    switch (OBJECT_TYPE(obj)) {
1670		case LispFixnum_t:
1671		    rmod_fi_fi(real, OFI(obj));
1672		    return;
1673		case LispInteger_t:
1674		    rmod_fi_fi(real, OII(obj));
1675		    return;
1676		case LispBignum_t:
1677		    rmod_fi_bi(real, OBI(obj));
1678		    return;
1679		default:
1680		    break;
1681	    }
1682	    break;
1683	case N_BIGNUM:
1684	    switch (OBJECT_TYPE(obj)) {
1685		case LispFixnum_t:
1686		    rmod_bi_fi(real, OFI(obj));
1687		    return;
1688		case LispInteger_t:
1689		    rmod_bi_fi(real, OII(obj));
1690		    return;
1691		case LispBignum_t:
1692		    rmod_bi_bi(real, OBI(obj));
1693		    return;
1694		default:
1695		    break;
1696	    }
1697	    break;
1698	/* Assume the n_real object is an integer */
1699    }
1700    fatal_object_error(obj, NOT_AN_INTEGER);
1701}
1702
1703static void
1704rmod_fi_fi(n_real *real, long fi)
1705{
1706    if (fi == 0)
1707	fatal_error(DIVIDE_BY_ZERO);
1708
1709    if ((RFI(real) < 0) ^ (fi < 0))
1710	RFI(real) = (RFI(real) % fi) + fi;
1711    else if (RFI(real) == MINSLONG || fi == MINSLONG) {
1712	mpi bignum;
1713
1714	mpi_init(&bignum);
1715	mpi_seti(&bignum, RFI(real));
1716	RFI(real) = mpi_modi(&bignum, fi);
1717	mpi_clear(&bignum);
1718    }
1719    else
1720	RFI(real) = RFI(real) % fi;
1721}
1722
1723static void
1724rmod_fi_bi(n_real *real, mpi *bignum)
1725{
1726    mpi *bigi;
1727
1728    if (mpi_cmpi(bignum, 0) == 0)
1729	fatal_error(DIVIDE_BY_ZERO);
1730
1731    bigi = XALLOC(mpi);
1732    mpi_init(bigi);
1733    mpi_seti(bigi, RFI(real));
1734    mpi_mod(bigi, bigi, bignum);
1735    RTYPE(real) = N_BIGNUM;
1736    RBI(real) = bigi;
1737    rbi_canonicalize(real);
1738}
1739
1740static void
1741rmod_bi_fi(n_real *real, long fi)
1742{
1743    mpi iop;
1744
1745    if (fi == 0)
1746	fatal_error(DIVIDE_BY_ZERO);
1747
1748    mpi_init(&iop);
1749    mpi_seti(&iop, fi);
1750    mpi_mod(RBI(real), RBI(real), &iop);
1751    mpi_clear(&iop);
1752    rbi_canonicalize(real);
1753}
1754
1755static void
1756rmod_bi_bi(n_real *real, mpi *bignum)
1757{
1758    if (mpi_cmpi(bignum, 0) == 0)
1759	fatal_error(DIVIDE_BY_ZERO);
1760
1761    mpi_mod(RBI(real), RBI(real), bignum);
1762    rbi_canonicalize(real);
1763}
1764
1765/************************************************************************
1766 * REM
1767 ************************************************************************/
1768static void
1769rem_real_object(n_real *real, LispObj *obj)
1770{
1771    switch (RTYPE(real)) {
1772	case N_FIXNUM:
1773	    switch (OBJECT_TYPE(obj)) {
1774		case LispFixnum_t:
1775		    rrem_fi_fi(real, OFI(obj));
1776		    return;
1777		case LispInteger_t:
1778		    rrem_fi_fi(real, OII(obj));
1779		    return;
1780		case LispBignum_t:
1781		    rrem_fi_bi(real, OBI(obj));
1782		    return;
1783		default:
1784		    break;
1785	    }
1786	    break;
1787	case N_BIGNUM:
1788	    switch (OBJECT_TYPE(obj)) {
1789		case LispFixnum_t:
1790		    rrem_bi_fi(real, OFI(obj));
1791		    return;
1792		case LispInteger_t:
1793		    rrem_bi_fi(real, OII(obj));
1794		    return;
1795		case LispBignum_t:
1796		    rrem_bi_bi(real, OBI(obj));
1797		    return;
1798		default:
1799		    break;
1800	    }
1801	    break;
1802	/* Assume the n_real object is an integer */
1803    }
1804    fatal_object_error(obj, NOT_AN_INTEGER);
1805}
1806
1807static void
1808rrem_fi_fi(n_real *real, long fi)
1809{
1810    if (fi == 0)
1811	fatal_error(DIVIDE_BY_ZERO);
1812
1813    if (RFI(real) == MINSLONG || fi == MINSLONG) {
1814	mpi bignum;
1815
1816	mpi_init(&bignum);
1817	mpi_seti(&bignum, RFI(real));
1818	RFI(real) = mpi_remi(&bignum, fi);
1819	mpi_clear(&bignum);
1820    }
1821    else
1822	RFI(real) = RFI(real) % fi;
1823}
1824
1825static void
1826rrem_fi_bi(n_real *real, mpi *bignum)
1827{
1828    mpi *bigi;
1829
1830    if (mpi_cmpi(bignum, 0) == 0)
1831	fatal_error(DIVIDE_BY_ZERO);
1832
1833    bigi = XALLOC(mpi);
1834    mpi_init(bigi);
1835    mpi_seti(bigi, RFI(real));
1836    mpi_rem(bigi, bigi, bignum);
1837    RTYPE(real) = N_BIGNUM;
1838    RBI(real) = bigi;
1839    rbi_canonicalize(real);
1840}
1841
1842static void
1843rrem_bi_fi(n_real *real, long fi)
1844{
1845    mpi iop;
1846
1847    if (fi == 0)
1848	fatal_error(DIVIDE_BY_ZERO);
1849
1850    mpi_init(&iop);
1851    mpi_seti(&iop, fi);
1852    mpi_rem(RBI(real), RBI(real), &iop);
1853    mpi_clear(&iop);
1854    rbi_canonicalize(real);
1855}
1856
1857static void
1858rrem_bi_bi(n_real *real, mpi *bignum)
1859{
1860    if (mpi_cmpi(bignum, 0) == 0)
1861	fatal_error(DIVIDE_BY_ZERO);
1862
1863    mpi_rem(RBI(real), RBI(real), bignum);
1864    rbi_canonicalize(real);
1865}
1866
1867
1868/************************************************************************
1869 * GCD
1870 ************************************************************************/
1871static void
1872gcd_real_object(n_real *real, LispObj *obj)
1873{
1874    if (!INTEGERP(obj))
1875	fatal_object_error(obj, NOT_AN_INTEGER);
1876
1877    /* check for zero operand */
1878    if (cmp_real_real(real, &zero) == 0)
1879	set_real_object(real, obj);
1880    else if (cmp_real_object(&zero, obj) != 0) {
1881	n_real rest, temp;
1882
1883	set_real_object(&rest, obj);
1884	for (;;) {
1885	    mod_real_real(&rest, real);
1886	    if (cmp_real_real(&rest, &zero) == 0)
1887		break;
1888	    memcpy(&temp, real, sizeof(n_real));
1889	    memcpy(real, &rest, sizeof(n_real));
1890	    memcpy(&rest, &temp, sizeof(n_real));
1891	}
1892	clear_real(&rest);
1893    }
1894}
1895
1896/************************************************************************
1897 * AND
1898 ************************************************************************/
1899static void
1900and_real_object(n_real *real, LispObj *obj)
1901{
1902    mpi *bigi, iop;
1903
1904    switch (OBJECT_TYPE(obj)) {
1905	case LispFixnum_t:
1906	    switch (RTYPE(real)) {
1907		case N_FIXNUM:
1908		    RFI(real) &= OFI(obj);
1909		    break;
1910		case N_BIGNUM:
1911		    mpi_init(&iop);
1912		    mpi_seti(&iop, OFI(obj));
1913		    mpi_and(RBI(real), RBI(real), &iop);
1914		    mpi_clear(&iop);
1915		    rbi_canonicalize(real);
1916		    break;
1917	    }
1918	    break;
1919	case LispInteger_t:
1920	    switch (RTYPE(real)) {
1921		case N_FIXNUM:
1922		    RFI(real) &= OII(obj);
1923		    break;
1924		case N_BIGNUM:
1925		    mpi_init(&iop);
1926		    mpi_seti(&iop, OII(obj));
1927		    mpi_and(RBI(real), RBI(real), &iop);
1928		    mpi_clear(&iop);
1929		    rbi_canonicalize(real);
1930		    break;
1931	    }
1932	    break;
1933	case LispBignum_t:
1934	    switch (RTYPE(real)) {
1935		case N_FIXNUM:
1936		    bigi = XALLOC(mpi);
1937		    mpi_init(bigi);
1938		    mpi_seti(bigi, RFI(real));
1939		    mpi_and(bigi, bigi, OBI(obj));
1940		    RTYPE(real) = N_BIGNUM;
1941		    RBI(real) = bigi;
1942		    rbi_canonicalize(real);
1943		    break;
1944		case N_BIGNUM:
1945		    mpi_and(RBI(real), RBI(real), OBI(obj));
1946		    rbi_canonicalize(real);
1947		    break;
1948	    }
1949	    break;
1950	default:
1951	    fatal_object_error(obj, NOT_AN_INTEGER);
1952	    break;
1953    }
1954}
1955
1956
1957/************************************************************************
1958 * EQV
1959 ************************************************************************/
1960static void
1961eqv_real_object(n_real *real, LispObj *obj)
1962{
1963    mpi *bigi, iop;
1964
1965    switch (OBJECT_TYPE(obj)) {
1966	case LispFixnum_t:
1967	    switch (RTYPE(real)) {
1968		case N_FIXNUM:
1969		    RFI(real) ^= ~OFI(obj);
1970		    break;
1971		case N_BIGNUM:
1972		    mpi_init(&iop);
1973		    mpi_seti(&iop, OFI(obj));
1974		    mpi_com(&iop, &iop);
1975		    mpi_xor(RBI(real), RBI(real), &iop);
1976		    mpi_clear(&iop);
1977		    rbi_canonicalize(real);
1978		    break;
1979	    }
1980	    break;
1981	case LispInteger_t:
1982	    switch (RTYPE(real)) {
1983		case N_FIXNUM:
1984		    RFI(real) ^= ~OII(obj);
1985		    break;
1986		case N_BIGNUM:
1987		    mpi_init(&iop);
1988		    mpi_seti(&iop, OII(obj));
1989		    mpi_com(&iop, &iop);
1990		    mpi_xor(RBI(real), RBI(real), &iop);
1991		    mpi_clear(&iop);
1992		    rbi_canonicalize(real);
1993		    break;
1994	    }
1995	    break;
1996	case LispBignum_t:
1997	    switch (RTYPE(real)) {
1998		case N_FIXNUM:
1999		    bigi = XALLOC(mpi);
2000		    mpi_init(bigi);
2001		    mpi_seti(bigi, RFI(real));
2002		    mpi_com(bigi, bigi);
2003		    mpi_xor(bigi, bigi, OBI(obj));
2004		    RTYPE(real) = N_BIGNUM;
2005		    RBI(real) = bigi;
2006		    rbi_canonicalize(real);
2007		    break;
2008		case N_BIGNUM:
2009		    mpi_com(RBI(real), RBI(real));
2010		    mpi_xor(RBI(real), RBI(real), OBI(obj));
2011		    rbi_canonicalize(real);
2012		    break;
2013	    }
2014	    break;
2015	default:
2016	    fatal_object_error(obj, NOT_AN_INTEGER);
2017	    break;
2018    }
2019}
2020
2021
2022/************************************************************************
2023 * IOR
2024 ************************************************************************/
2025static void
2026ior_real_object(n_real *real, LispObj *obj)
2027{
2028    mpi *bigi, iop;
2029
2030    switch (OBJECT_TYPE(obj)) {
2031	case LispFixnum_t:
2032	    switch (RTYPE(real)) {
2033		case N_FIXNUM:
2034		    RFI(real) |= OFI(obj);
2035		    break;
2036		case N_BIGNUM:
2037		    mpi_init(&iop);
2038		    mpi_seti(&iop, OFI(obj));
2039		    mpi_ior(RBI(real), RBI(real), &iop);
2040		    mpi_clear(&iop);
2041		    rbi_canonicalize(real);
2042		    break;
2043	    }
2044	    break;
2045	case LispInteger_t:
2046	    switch (RTYPE(real)) {
2047		case N_FIXNUM:
2048		    RFI(real) |= OII(obj);
2049		    break;
2050		case N_BIGNUM:
2051		    mpi_init(&iop);
2052		    mpi_seti(&iop, OII(obj));
2053		    mpi_ior(RBI(real), RBI(real), &iop);
2054		    mpi_clear(&iop);
2055		    rbi_canonicalize(real);
2056		    break;
2057	    }
2058	    break;
2059	case LispBignum_t:
2060	    switch (RTYPE(real)) {
2061		case N_FIXNUM:
2062		    bigi = XALLOC(mpi);
2063		    mpi_init(bigi);
2064		    mpi_seti(bigi, RFI(real));
2065		    mpi_ior(bigi, bigi, OBI(obj));
2066		    RTYPE(real) = N_BIGNUM;
2067		    RBI(real) = bigi;
2068		    rbi_canonicalize(real);
2069		    break;
2070		case N_BIGNUM:
2071		    mpi_ior(RBI(real), RBI(real), OBI(obj));
2072		    rbi_canonicalize(real);
2073		    break;
2074	    }
2075	    break;
2076	default:
2077	    fatal_object_error(obj, NOT_AN_INTEGER);
2078	    break;
2079    }
2080}
2081
2082
2083/************************************************************************
2084 * NOT
2085 ************************************************************************/
2086static void
2087not_real(n_real *real)
2088{
2089    if (RTYPE(real) == N_FIXNUM)
2090	RFI(real) = ~RFI(real);
2091    else {
2092	mpi_com(RBI(real), RBI(real));
2093	rbi_canonicalize(real);
2094    }
2095}
2096
2097/************************************************************************
2098 * XOR
2099 ************************************************************************/
2100static void
2101xor_real_object(n_real *real, LispObj *obj)
2102{
2103    mpi *bigi, iop;
2104
2105    switch (OBJECT_TYPE(obj)) {
2106	case LispFixnum_t:
2107	    switch (RTYPE(real)) {
2108		case N_FIXNUM:
2109		    RFI(real) ^= OFI(obj);
2110		    break;
2111		case N_BIGNUM:
2112		    mpi_init(&iop);
2113		    mpi_seti(&iop, OFI(obj));
2114		    mpi_xor(RBI(real), RBI(real), &iop);
2115		    mpi_clear(&iop);
2116		    rbi_canonicalize(real);
2117		    break;
2118	    }
2119	    break;
2120	case LispInteger_t:
2121	    switch (RTYPE(real)) {
2122		case N_FIXNUM:
2123		    RFI(real) ^= OII(obj);
2124		    break;
2125		case N_BIGNUM:
2126		    mpi_init(&iop);
2127		    mpi_seti(&iop, OII(obj));
2128		    mpi_xor(RBI(real), RBI(real), &iop);
2129		    mpi_clear(&iop);
2130		    rbi_canonicalize(real);
2131		    break;
2132	    }
2133	    break;
2134	case LispBignum_t:
2135	    switch (RTYPE(real)) {
2136		case N_FIXNUM:
2137		    bigi = XALLOC(mpi);
2138		    mpi_init(bigi);
2139		    mpi_seti(bigi, RFI(real));
2140		    mpi_xor(bigi, bigi, OBI(obj));
2141		    RTYPE(real) = N_BIGNUM;
2142		    RBI(real) = bigi;
2143		    rbi_canonicalize(real);
2144		    break;
2145		case N_BIGNUM:
2146		    mpi_xor(RBI(real), RBI(real), OBI(obj));
2147		    rbi_canonicalize(real);
2148		    break;
2149	    }
2150	    break;
2151	default:
2152	    fatal_object_error(obj, NOT_AN_INTEGER);
2153	    break;
2154    }
2155}
2156
2157
2158/************************************************************************
2159 * DIVIDE
2160 ************************************************************************/
2161static void
2162divide_number_object(n_number *num, LispObj *obj, int fun, int flo)
2163{
2164    switch (OBJECT_TYPE(obj)) {
2165	case LispFixnum_t:
2166	    switch (NRTYPE(num)) {
2167		case N_FIXNUM:
2168		    ndivide_fi_fi(num, OFI(obj), fun, flo);
2169		    break;
2170		case N_BIGNUM:
2171		    ndivide_xi_xi(num, obj, fun, flo);
2172		    break;
2173		case N_FLONUM:
2174		    ndivide_flonum(num, NRFF(num), (double)OFI(obj), fun, flo);
2175		    break;
2176		case N_FIXRATIO:
2177		case N_BIGRATIO:
2178		    ndivide_xr_xi(num, obj, fun, flo);
2179		    break;
2180	    }
2181	    break;
2182	case LispInteger_t:
2183	    switch (NRTYPE(num)) {
2184		case N_FIXNUM:
2185		    ndivide_fi_fi(num, OII(obj), fun, flo);
2186		    break;
2187		case N_BIGNUM:
2188		    ndivide_xi_xi(num, obj, fun, flo);
2189		    break;
2190		case N_FLONUM:
2191		    ndivide_flonum(num, NRFF(num), (double)OII(obj), fun, flo);
2192		    break;
2193		case N_FIXRATIO:
2194		case N_BIGRATIO:
2195		    ndivide_xr_xi(num, obj, fun, flo);
2196		    break;
2197	    }
2198	    break;
2199	case LispBignum_t:
2200	    switch (NRTYPE(num)) {
2201		case N_FIXNUM:
2202		case N_BIGNUM:
2203		    ndivide_xi_xi(num, obj, fun, flo);
2204		    break;
2205		case N_FLONUM:
2206		    ndivide_flonum(num, NRFF(num), bi_getd(OBI(obj)),
2207				   fun, flo);
2208		    break;
2209		case N_FIXRATIO:
2210		case N_BIGRATIO:
2211		    ndivide_xr_xi(num, obj, fun, flo);
2212		    break;
2213	    }
2214	    break;
2215	case LispDFloat_t:
2216	    switch (NRTYPE(num)) {
2217		case N_FIXNUM:
2218		    ndivide_flonum(num, (double)NRFI(num), ODF(obj),
2219				   fun, flo);
2220		    break;
2221		case N_BIGNUM:
2222		    ndivide_flonum(num, bi_getd(NRBI(num)), ODF(obj),
2223				   fun, flo);
2224		    break;
2225		case N_FLONUM:
2226		    ndivide_flonum(num, NRFF(num), ODF(obj), fun, flo);
2227		    break;
2228		case N_FIXRATIO:
2229		    ndivide_flonum(num,
2230				   (double)NRFRN(num) / (double)NRFRD(num),
2231				   ODF(obj), fun, flo);
2232		    break;
2233		case N_BIGRATIO:
2234		    ndivide_flonum(num, br_getd(NRBR(num)), ODF(obj),
2235				   fun, flo);
2236		    break;
2237	    }
2238	    break;
2239	case LispRatio_t:
2240	    switch (NRTYPE(num)) {
2241		case N_FIXNUM:
2242		case N_BIGNUM:
2243		    ndivide_xi_xr(num, obj, fun, flo);
2244		    break;
2245		case N_FLONUM:
2246		    ndivide_flonum(num, NRFF(num),
2247				   (double)OFRN(obj) / (double)OFRD(obj),
2248				   fun, flo);
2249		    break;
2250		case N_FIXRATIO:
2251		case N_BIGRATIO:
2252		    ndivide_xr_xr(num, obj, fun, flo);
2253		    break;
2254	    }
2255	    break;
2256	case LispBigratio_t:
2257	    switch (NRTYPE(num)) {
2258		case N_FIXNUM:
2259		case N_BIGNUM:
2260		    ndivide_xi_xr(num, obj, fun, flo);
2261		    break;
2262		case N_FLONUM:
2263		    ndivide_flonum(num, NRFF(num), br_getd(OBR(obj)),
2264				   fun, flo);
2265		    break;
2266		case N_FIXRATIO:
2267		case N_BIGRATIO:
2268		    ndivide_xr_xr(num, obj, fun, flo);
2269		    break;
2270	    }
2271	    break;
2272	default:
2273	    fatal_object_error(obj, NOT_A_REAL_NUMBER);
2274	    break;
2275    }
2276}
2277
2278
2279/************************************************************************
2280 * COMPARE
2281 ************************************************************************/
2282static int
2283cmp_real_real(n_real *op1, n_real *op2)
2284{
2285    switch (RTYPE(op1)) {
2286	case N_FIXNUM:
2287	    switch (RTYPE(op2)) {
2288		case N_FIXNUM:
2289		    return (cmp_fi_fi(RFI(op1), RFI(op2)));
2290		case N_BIGNUM:
2291		    return (cmp_fi_bi(RFI(op1), RBI(op2)));
2292		case N_FLONUM:
2293		    return (cmp_flonum((double)RFI(op1), RFF(op2)));
2294		case N_FIXRATIO:
2295		    return (cmp_fi_fr(RFI(op1), RFRN(op2), RFRD(op2)));
2296		case N_BIGRATIO:
2297		    return (cmp_fi_br(RFI(op1), RBR(op2)));
2298	    }
2299	    break;
2300	case N_BIGNUM:
2301	    switch (RTYPE(op2)) {
2302		case N_FIXNUM:
2303		    return (cmp_bi_fi(RBI(op1), RFI(op2)));
2304		case N_BIGNUM:
2305		    return (cmp_bi_bi(RBI(op1), RBI(op2)));
2306		case N_FLONUM:
2307		    return (cmp_flonum(bi_getd(RBI(op1)), RFF(op2)));
2308		case N_FIXRATIO:
2309		    return (cmp_bi_fr(RBI(op1), RFRN(op2), RFRD(op2)));
2310		case N_BIGRATIO:
2311		    return (cmp_bi_br(RBI(op1), RBR(op2)));
2312	    }
2313	    break;
2314	case N_FLONUM:
2315	    switch (RTYPE(op2)) {
2316		case N_FIXNUM:
2317		    return (cmp_flonum(RFF(op1), (double)RFI(op2)));
2318		case N_BIGNUM:
2319		    return (cmp_flonum(RFF(op1), bi_getd(RBI(op2))));
2320		case N_FLONUM:
2321		    return (cmp_flonum(RFF(op1), RFF(op2)));
2322		case N_FIXRATIO:
2323		    return (cmp_flonum(RFF(op1),
2324				       (double)RFRN(op2) / (double)RFRD(op2)));
2325		case N_BIGRATIO:
2326		    return (cmp_flonum(RFF(op1), br_getd(RBR(op2))));
2327	    }
2328	    break;
2329	case N_FIXRATIO:
2330	    switch (RTYPE(op2)) {
2331		case N_FIXNUM:
2332		    return (cmp_fr_fi(RFRN(op1), RFRD(op1), RFI(op2)));
2333		case N_BIGNUM:
2334		    return (cmp_fr_bi(RFRN(op1), RFRD(op1), RBI(op2)));
2335		case N_FLONUM:
2336		    return (cmp_flonum((double)RFRN(op1) / (double)RFRD(op1),
2337				       RFF(op2)));
2338		case N_FIXRATIO:
2339		    return (cmp_fr_fr(RFRN(op1), RFRD(op1),
2340				      RFRN(op2), RFRD(op2)));
2341		case N_BIGRATIO:
2342		    return (cmp_fr_br(RFRN(op1), RFRD(op1), RBR(op2)));
2343	    }
2344	    break;
2345	case N_BIGRATIO:
2346	    switch (RTYPE(op2)) {
2347		case N_FIXNUM:
2348		    return (cmp_br_fi(RBR(op1), RFI(op2)));
2349		case N_BIGNUM:
2350		    return (cmp_br_bi(RBR(op1), RBI(op2)));
2351		case N_FLONUM:
2352		    return (cmp_flonum(br_getd(RBR(op1)), RFF(op2)));
2353		case N_FIXRATIO:
2354		    return (cmp_br_fr(RBR(op1), RFRN(op2), RFRD(op2)));
2355		case N_BIGRATIO:
2356		    return (cmp_br_br(RBR(op1), RBR(op2)));
2357	    }
2358    }
2359
2360    return (0);
2361}
2362
2363static int
2364cmp_real_object(n_real *op1, LispObj *op2)
2365{
2366    switch (OBJECT_TYPE(op2)) {
2367	case LispFixnum_t:
2368	    switch (RTYPE(op1)) {
2369		case N_FIXNUM:
2370		    return (cmp_fi_fi(RFI(op1), OFI(op2)));
2371		case N_BIGNUM:
2372		    return (cmp_bi_fi(RBI(op1), OFI(op2)));
2373		case N_FLONUM:
2374		    return (cmp_flonum(RFF(op1), (double)OFI(op2)));
2375		case N_FIXRATIO:
2376		    return (cmp_fr_fi(RFRD(op1), RFRN(op1), OFI(op2)));
2377		case N_BIGRATIO:
2378		    return (cmp_br_fi(RBR(op1), OFI(op2)));
2379	    }
2380	    break;
2381	case LispInteger_t:
2382	    switch (RTYPE(op1)) {
2383		case N_FIXNUM:
2384		    return (cmp_fi_fi(RFI(op1), OII(op2)));
2385		case N_BIGNUM:
2386		    return (cmp_bi_fi(RBI(op1), OII(op2)));
2387		case N_FLONUM:
2388		    return (cmp_flonum(RFF(op1), (double)OII(op2)));
2389		case N_FIXRATIO:
2390		    return (cmp_fr_fi(RFRD(op1), RFRN(op1), OII(op2)));
2391		case N_BIGRATIO:
2392		    return (cmp_br_fi(RBR(op1), OII(op2)));
2393	    }
2394	    break;
2395	case LispBignum_t:
2396	    switch (RTYPE(op1)) {
2397		case N_FIXNUM:
2398		    return (cmp_fi_bi(RFI(op1), OBI(op2)));
2399		case N_BIGNUM:
2400		    return (cmp_bi_bi(RBI(op1), OBI(op2)));
2401		case N_FLONUM:
2402		    return (cmp_flonum(RFF(op1), bi_getd(OBI(op2))));
2403		case N_FIXRATIO:
2404		    return (cmp_fr_bi(RFRD(op1), RFRN(op1), OBI(op2)));
2405		case N_BIGRATIO:
2406		    return (cmp_br_bi(RBR(op1), OBI(op2)));
2407	    }
2408	    break;
2409	case LispDFloat_t:
2410	    switch (RTYPE(op1)) {
2411		case N_FIXNUM:
2412		    return (cmp_flonum((double)RFI(op1), ODF(op2)));
2413		case N_BIGNUM:
2414		    return (cmp_flonum(bi_getd(RBI(op1)), ODF(op2)));
2415		case N_FLONUM:
2416		    return (cmp_flonum(RFF(op1), ODF(op2)));
2417		case N_FIXRATIO:
2418		    return (cmp_flonum((double)RFRN(op1) / (double)RFRD(op1),
2419				       ODF(op2)));
2420		case N_BIGRATIO:
2421		    return (cmp_flonum(br_getd(RBR(op1)), ODF(op2)));
2422	    }
2423	    break;
2424	case LispRatio_t:
2425	    switch (RTYPE(op1)) {
2426		case N_FIXNUM:
2427		    return (cmp_fi_fr(RFI(op1), OFRN(op2), OFRD(op2)));
2428		case N_BIGNUM:
2429		    return (cmp_bi_fr(RBI(op1), OFRN(op2), OFRD(op2)));
2430		case N_FLONUM:
2431		    return (cmp_flonum(RFF(op1),
2432				       (double)OFRN(op2) / (double)OFRD(op2)));
2433		case N_FIXRATIO:
2434		    return (cmp_fr_fr(RFRN(op1), RFRD(op1),
2435				      OFRN(op2), OFRD(op2)));
2436		case N_BIGRATIO:
2437		    return (cmp_br_fr(RBR(op1), OFRN(op2), OFRD(op2)));
2438	    }
2439	    break;
2440	case LispBigratio_t:
2441	    switch (RTYPE(op1)) {
2442		case N_FIXNUM:
2443		    return (cmp_fi_br(RFI(op1), OBR(op2)));
2444		case N_BIGNUM:
2445		    return (cmp_bi_br(RBI(op1), OBR(op2)));
2446		case N_FLONUM:
2447		    return (cmp_flonum(RFF(op1), br_getd(OBR(op2))));
2448		case N_FIXRATIO:
2449		    return (cmp_fr_br(RFRN(op1), RFRD(op1), OBR(op2)));
2450		case N_BIGRATIO:
2451		    return (cmp_br_br(RBR(op1), OBR(op2)));
2452	    }
2453	    break;
2454	default:
2455	    fatal_object_error(op2, NOT_A_REAL_NUMBER);
2456	    break;
2457    }
2458
2459    return (0);
2460}
2461
2462#if 0		/* not used */
2463static int
2464cmp_number_object(n_number *op1, LispObj *op2)
2465{
2466    if (op1->complex) {
2467	if (OBJECT_TYPE(op2) == LispComplex_t) {
2468	    if (cmp_real_object(NREAL(op1), OCXR(op2)) == 0)
2469		return (cmp_real_object(NIMAG(op1), OCXI(op2)));
2470	    return (1);
2471	}
2472	else if (cmp_real_real(NIMAG(op1), &zero) == 0)
2473	    return (cmp_real_object(NREAL(op1), op2));
2474	else
2475	    return (1);
2476    }
2477    else {
2478	switch (OBJECT_TYPE(op2)) {
2479	    case LispFixnum_t:
2480		switch (NRTYPE(op1)) {
2481		    case N_FIXNUM:
2482			return (cmp_fi_fi(NRFI(op1), OFI(op2)));
2483		    case N_BIGNUM:
2484			return (cmp_bi_fi(NRBI(op1), OFI(op2)));
2485		    case N_FLONUM:
2486			return (cmp_flonum(NRFF(op1), (double)OFI(op2)));
2487		    case N_FIXRATIO:
2488			return (cmp_fr_fi(NRFRD(op1), NRFRN(op1), OFI(op2)));
2489		    case N_BIGRATIO:
2490			return (cmp_br_fi(NRBR(op1), OFI(op2)));
2491		}
2492		break;
2493	    case LispInteger_t:
2494		switch (NRTYPE(op1)) {
2495		    case N_FIXNUM:
2496			return (cmp_fi_fi(NRFI(op1), OII(op2)));
2497		    case N_BIGNUM:
2498			return (cmp_bi_fi(NRBI(op1), OII(op2)));
2499		    case N_FLONUM:
2500			return (cmp_flonum(NRFF(op1), (double)OII(op2)));
2501		    case N_FIXRATIO:
2502			return (cmp_fr_fi(NRFRD(op1), NRFRN(op1), OII(op2)));
2503		    case N_BIGRATIO:
2504			return (cmp_br_fi(NRBR(op1), OII(op2)));
2505		}
2506		break;
2507	    case LispBignum_t:
2508		switch (NRTYPE(op1)) {
2509		    case N_FIXNUM:
2510			return (cmp_fi_bi(NRFI(op1), OBI(op2)));
2511		    case N_BIGNUM:
2512			return (cmp_bi_bi(NRBI(op1), OBI(op2)));
2513		    case N_FLONUM:
2514			return (cmp_flonum(NRFF(op1), bi_getd(OBI(op2))));
2515		    case N_FIXRATIO:
2516			return (cmp_fr_bi(NRFRD(op1), NRFRN(op1), OBI(op2)));
2517		    case N_BIGRATIO:
2518			return (cmp_br_bi(NRBR(op1), OBI(op2)));
2519		}
2520		break;
2521	    case LispDFloat_t:
2522		switch (NRTYPE(op1)) {
2523		    case N_FIXNUM:
2524			return (cmp_flonum((double)NRFI(op1), ODF(op2)));
2525		    case N_BIGNUM:
2526			return (cmp_flonum(bi_getd(NRBI(op1)), ODF(op2)));
2527		    case N_FLONUM:
2528			return (cmp_flonum(NRFF(op1), ODF(op2)));
2529		    case N_FIXRATIO:
2530			return (cmp_flonum((double)NRFRN(op1) /
2531					   (double)NRFRD(op1),
2532					   ODF(op2)));
2533		    case N_BIGRATIO:
2534			return (cmp_flonum(br_getd(NRBR(op1)), ODF(op2)));
2535		}
2536		break;
2537	    case LispRatio_t:
2538		switch (NRTYPE(op1)) {
2539		    case N_FIXNUM:
2540			return (cmp_fi_fr(NRFI(op1), OFRN(op2), OFRD(op2)));
2541		    case N_BIGNUM:
2542			return (cmp_bi_fr(NRBI(op1), OFRN(op2), OFRD(op2)));
2543		    case N_FLONUM:
2544			return (cmp_flonum(NRFF(op1),
2545					   (double)OFRN(op2) / (double)OFRD(op2)));
2546		    case N_FIXRATIO:
2547			return (cmp_fr_fr(NRFRN(op1), NRFRD(op1),
2548					  OFRN(op2), OFRD(op2)));
2549		    case N_BIGRATIO:
2550			return (cmp_br_fr(NRBR(op1), OFRN(op2), OFRD(op2)));
2551		}
2552		break;
2553	    case LispBigratio_t:
2554		switch (NRTYPE(op1)) {
2555		    case N_FIXNUM:
2556			return (cmp_fi_br(NRFI(op1), OBR(op2)));
2557		    case N_BIGNUM:
2558			return (cmp_bi_br(NRBI(op1), OBR(op2)));
2559		    case N_FLONUM:
2560			return (cmp_flonum(NRFF(op1), br_getd(OBR(op2))));
2561		    case N_FIXRATIO:
2562			return (cmp_fr_br(NRFRN(op1), NRFRD(op1), OBR(op2)));
2563		    case N_BIGRATIO:
2564			return (cmp_br_br(NRBR(op1), OBR(op2)));
2565		}
2566		break;
2567	    case LispComplex_t:
2568		if (cmp_real_object(&zero, OCXI(op2)) == 0)
2569		    return (cmp_real_object(NREAL(op1), OCXR(op2)));
2570		return (1);
2571	    default:
2572		fatal_object_error(op2, NOT_A_NUMBER);
2573		break;
2574	}
2575    }
2576
2577    return (0);
2578}
2579#endif
2580
2581static int
2582cmp_object_object(LispObj *op1, LispObj *op2, int real)
2583{
2584    if (OBJECT_TYPE(op1) == LispComplex_t) {
2585	if (real)
2586	    fatal_object_error(op1, NOT_A_REAL_NUMBER);
2587	if (OBJECT_TYPE(op2) == LispComplex_t)
2588	    return (cmp_cx_cx(op1, op2));
2589	else if (cmp_real_object(&zero, OCXI(op1)) == 0)
2590	    return (cmp_object_object(OCXR(op1), op2, real));
2591	return (1);
2592    }
2593    else if (OBJECT_TYPE(op2) == LispComplex_t) {
2594	if (real)
2595	    fatal_object_error(op1, NOT_A_REAL_NUMBER);
2596	if (cmp_real_object(&zero, OCXI(op2)) == 0)
2597	    return (cmp_object_object(op1, OCXR(op2), real));
2598	return (1);
2599    }
2600    else {
2601	switch (OBJECT_TYPE(op1)) {
2602	    case LispFixnum_t:
2603		switch (OBJECT_TYPE(op2)) {
2604		    case LispFixnum_t:
2605			return (cmp_fi_fi(OFI(op1), OFI(op2)));
2606		    case LispInteger_t:
2607			return (cmp_fi_fi(OFI(op1), OII(op2)));
2608		    case LispBignum_t:
2609			return (cmp_fi_bi(OFI(op1), OBI(op2)));
2610		    case LispDFloat_t:
2611			return (cmp_flonum((double)OFI(op1), ODF(op2)));
2612		    case LispRatio_t:
2613			return (cmp_fi_fr(OFI(op1),
2614					  OFRN(op2), OFRD(op2)));
2615		    case LispBigratio_t:
2616			return (cmp_fi_br(OFI(op1), OBR(op2)));
2617		    default:
2618			break;
2619		}
2620		break;
2621	    case LispInteger_t:
2622		switch (OBJECT_TYPE(op2)) {
2623		    case LispFixnum_t:
2624			return (cmp_fi_fi(OII(op1), OFI(op2)));
2625		    case LispInteger_t:
2626			return (cmp_fi_fi(OII(op1), OII(op2)));
2627		    case LispBignum_t:
2628			return (cmp_fi_bi(OII(op1), OBI(op2)));
2629		    case LispDFloat_t:
2630			return (cmp_flonum((double)OII(op1), ODF(op2)));
2631		    case LispRatio_t:
2632			return (cmp_fi_fr(OII(op1),
2633					  OFRN(op2), OFRD(op2)));
2634		    case LispBigratio_t:
2635			return (cmp_fi_br(OII(op1), OBR(op2)));
2636		    default:
2637			break;
2638		}
2639		break;
2640	    case LispBignum_t:
2641		switch (OBJECT_TYPE(op2)) {
2642		    case LispFixnum_t:
2643			return (cmp_bi_fi(OBI(op1), OFI(op2)));
2644		    case LispInteger_t:
2645			return (cmp_bi_fi(OBI(op1), OII(op2)));
2646		    case LispBignum_t:
2647			return (cmp_bi_bi(OBI(op1), OBI(op2)));
2648		    case LispDFloat_t:
2649			return (cmp_flonum(bi_getd(OBI(op1)), ODF(op2)));
2650		    case LispRatio_t:
2651			return (cmp_bi_fr(OBI(op1),
2652					  OFRN(op2), OFRD(op2)));
2653		    case LispBigratio_t:
2654			return (cmp_bi_br(OBI(op1), OBR(op2)));
2655		    default:
2656			break;
2657		}
2658		break;
2659	    case LispDFloat_t:
2660		switch (OBJECT_TYPE(op2)) {
2661		    case LispFixnum_t:
2662			return (cmp_flonum(ODF(op1), (double)OFI(op2)));
2663		    case LispInteger_t:
2664			return (cmp_flonum(ODF(op1), (double)OII(op2)));
2665		    case LispBignum_t:
2666			return (cmp_flonum(ODF(op1), bi_getd(OBI(op2))));
2667		    case LispDFloat_t:
2668			return (cmp_flonum(ODF(op1), ODF(op2)));
2669			break;
2670		    case LispRatio_t:
2671			return (cmp_flonum(ODF(op1),
2672					   (double)OFRN(op2) /
2673					   (double)OFRD(op2)));
2674		    case LispBigratio_t:
2675			return (cmp_flonum(ODF(op1), br_getd(OBR(op2))));
2676		    default:
2677			break;
2678		}
2679		break;
2680	    case LispRatio_t:
2681		switch (OBJECT_TYPE(op2)) {
2682		    case LispFixnum_t:
2683			return (cmp_fr_fi(OFRN(op1), OFRD(op1), OFI(op2)));
2684		    case LispInteger_t:
2685			return (cmp_fr_fi(OFRN(op1), OFRD(op1), OII(op2)));
2686		    case LispBignum_t:
2687			return (cmp_fr_bi(OFRN(op1), OFRD(op1), OBI(op2)));
2688		    case LispDFloat_t:
2689			return (cmp_flonum((double)OFRN(op1) /
2690					   (double)OFRD(op1),
2691					   ODF(op2)));
2692		    case LispRatio_t:
2693			return (cmp_fr_fr(OFRN(op1), OFRD(op1),
2694					  OFRN(op2), OFRD(op2)));
2695		    case LispBigratio_t:
2696			return (cmp_fr_br(OFRN(op1), OFRD(op1), OBR(op2)));
2697		    default:
2698			break;
2699		}
2700		break;
2701	    case LispBigratio_t:
2702		switch (OBJECT_TYPE(op2)) {
2703		    case LispFixnum_t:
2704			return (cmp_br_fi(OBR(op1), OFI(op2)));
2705		    case LispInteger_t:
2706			return (cmp_br_fi(OBR(op1), OII(op2)));
2707		    case LispBignum_t:
2708			return (cmp_br_bi(OBR(op1), OBI(op2)));
2709		    case LispDFloat_t:
2710			return (cmp_flonum(br_getd(OBR(op1)), ODF(op2)));
2711		    case LispRatio_t:
2712			return (cmp_br_fr(OBR(op1), OFRN(op2), OFRD(op2)));
2713		    case LispBigratio_t:
2714			return (cmp_br_br(OBR(op1), OBR(op2)));
2715		    default:
2716			break;
2717		}
2718		break;
2719	    default:
2720		fatal_object_error(op1, NOT_A_NUMBER);
2721		break;
2722	}
2723    }
2724
2725    fatal_object_error(op2, NOT_A_NUMBER);
2726    return (0);
2727}
2728
2729
2730/************************************************************************
2731 * FIXNUM
2732 ************************************************************************/
2733/*
2734 * check if op1 + op2 will overflow
2735 */
2736static INLINE int
2737fi_fi_add_overflow(long op1, long op2)
2738{
2739    long op = op1 + op2;
2740
2741    return (op1 > 0 ? op2 > op : op2 < op);
2742}
2743
2744/*
2745 * check if op1 - op2 will overflow
2746 */
2747static INLINE int
2748fi_fi_sub_overflow(long op1, long op2)
2749{
2750    long op = op1 - op2;
2751
2752    return (((op1 < 0) ^ (op2 < 0)) && ((op < 0) ^ (op1 < 0)));
2753}
2754
2755/*
2756 * check if op1 * op2 will overflow
2757 */
2758static INLINE int
2759fi_fi_mul_overflow(long op1, long op2)
2760{
2761#ifndef LONG64
2762    double op = (double)op1 * (double)op2;
2763
2764    return (op > 2147483647.0 || op < -2147483648.0);
2765#else
2766    int shift;
2767    long mask;
2768
2769    if (op1 == 0 || op1 == 1 || op2 == 0 || op2 == 1)
2770	return (0);
2771
2772    if (op1 == MINSLONG || op2 == MINSLONG)
2773	return (1);
2774
2775    if (op1 < 0)
2776	op1 = -op1;
2777    if (op2 < 0)
2778	op2 = -op2;
2779
2780    for (shift = 0, mask = FI_MASK; shift < LONGSBITS; shift++, mask >>= 1)
2781	if (op1 & mask)
2782	    break;
2783    ++shift;
2784    for (mask = FI_MASK; shift < LONGSBITS; shift++, mask >>= 1)
2785	if (op2 & mask)
2786	    break;
2787
2788    return (shift < LONGSBITS);
2789#endif
2790}
2791
2792
2793/************************************************************************
2794 * BIGNUM
2795 ************************************************************************/
2796static void
2797rbi_canonicalize(n_real *real)
2798{
2799    if (mpi_fiti(RBI(real))) {
2800	long fi = mpi_geti(RBI(real));
2801
2802	RTYPE(real) = N_FIXNUM;
2803	mpi_clear(RBI(real));
2804	XFREE(RBI(real));
2805	RFI(real) = fi;
2806    }
2807}
2808
2809
2810/************************************************************************
2811 * RATIO
2812 ************************************************************************/
2813static void
2814rfr_canonicalize(n_real *real)
2815{
2816    long num, numerator, den, denominator, rest;
2817
2818    num = numerator = RFRN(real);
2819    den = denominator = RFRD(real);
2820    if (denominator == 0)
2821	fatal_error(DIVIDE_BY_ZERO);
2822
2823    if (num == MINSLONG || den == MINSLONG) {
2824	mpr *bigratio = XALLOC(mpr);
2825
2826	mpr_init(bigratio);
2827	mpr_seti(bigratio, num, den);
2828	RTYPE(real) = N_BIGRATIO;
2829	RBR(real) = bigratio;
2830	rbr_canonicalize(real);
2831	return;
2832    }
2833
2834    if (num < 0)
2835	num = -num;
2836    else if (num == 0) {
2837	RFI(real) = 0;
2838	RTYPE(real) = N_FIXNUM;
2839	return;
2840    }
2841    for (;;) {
2842	if ((rest = den % num) == 0)
2843	    break;
2844	den = num;
2845	num = rest;
2846    }
2847    if (den != 1) {
2848	denominator /= num;
2849	numerator /= num;
2850    }
2851    if (denominator < 0) {
2852	numerator = -numerator;
2853	denominator = -denominator;
2854    }
2855    if (denominator == 1) {
2856	RTYPE(real) = N_FIXNUM;
2857	RFI(real) = numerator;
2858    }
2859    else {
2860	RFRN(real) = numerator;
2861	RFRD(real) = denominator;
2862    }
2863}
2864
2865static void
2866rbr_canonicalize(n_real *real)
2867{
2868    int fitnum, fitden;
2869    long numerator, denominator;
2870
2871    mpr_canonicalize(RBR(real));
2872    fitnum = mpi_fiti(RBRN(real));
2873    fitden = mpi_fiti(RBRD(real));
2874    if (fitnum && fitden) {
2875	numerator = mpi_geti(RBRN(real));
2876	denominator = mpi_geti(RBRD(real));
2877	mpr_clear(RBR(real));
2878	XFREE(RBR(real));
2879	if (numerator == 0) {
2880	    RFI(real) = 0;
2881	    RTYPE(real) = N_FIXNUM;
2882	}
2883	else if (denominator == 1) {
2884	    RTYPE(real) = N_FIXNUM;
2885	    RFI(real) = numerator;
2886	}
2887	else {
2888	    RTYPE(real) = N_FIXRATIO;
2889	    RFRN(real) = numerator;
2890	    RFRD(real) = denominator;
2891	}
2892    }
2893    else if (fitden) {
2894	denominator = mpi_geti(RBRD(real));
2895	if (denominator == 1) {
2896	    mpi *bigi = XALLOC(mpi);
2897
2898	    mpi_init(bigi);
2899	    mpi_set(bigi, RBRN(real));
2900	    mpr_clear(RBR(real));
2901	    XFREE(RBR(real));
2902	    RTYPE(real) = N_BIGNUM;
2903	    RBI(real) = bigi;
2904	}
2905	else if (denominator == 0)
2906	    fatal_error(DIVIDE_BY_ZERO);
2907    }
2908}
2909
2910
2911/************************************************************************
2912 * COMPLEX
2913 ************************************************************************/
2914static void
2915ncx_canonicalize(n_number *num)
2916{
2917    if (NITYPE(num) == N_FIXNUM && NIFI(num) == 0)
2918	num->complex = 0;
2919}
2920
2921
2922/************************************************************************
2923 * DIVIDE
2924 ************************************************************************/
2925#define NDIVIDE_NOP	0
2926#define NDIVIDE_ADD	1
2927#define NDIVIDE_SUB	2
2928static void
2929ndivide_fi_fi(n_number *num, long div, int fun, int flo)
2930{
2931    long quo, rem;
2932
2933    if (NRFI(num) == MINSLONG || div == MINSLONG) {
2934	LispObj integer;
2935	mpi *bignum = XALLOC(mpi);
2936
2937	mpi_init(bignum);
2938	mpi_seti(bignum, NRFI(num));
2939	NRBI(num) = bignum;
2940	NRTYPE(num) = N_BIGNUM;
2941	integer.type = LispInteger_t;
2942	integer.data.integer = div;
2943	ndivide_xi_xi(num, &integer, fun, flo);
2944	return;
2945    }
2946    else {
2947	quo = NRFI(num) / div;
2948	rem = NRFI(num) % div;
2949    }
2950
2951    switch (fun) {
2952	case NDIVIDE_CEIL:
2953	    if ((rem < 0 && div < 0) || (rem > 0 && div > 0)) {
2954		++quo;
2955		rem -= div;
2956	    }
2957	    break;
2958	case NDIVIDE_FLOOR:
2959	    if ((rem < 0 && div > 0) || (rem > 0 && div < 0)) {
2960		--quo;
2961		rem += div;
2962	    }
2963	    break;
2964	case NDIVIDE_ROUND:
2965	    if (div > 0) {
2966		if (rem > 0) {
2967		    if (rem >= (div + 1) / 2) {
2968			++quo;
2969			rem -= div;
2970		    }
2971		}
2972		else {
2973		    if (rem <= (-div - 1) / 2) {
2974			--quo;
2975			rem += div;
2976		    }
2977		}
2978	    }
2979	    else {
2980		if (rem > 0) {
2981		    if (rem >= (-div + 1) / 2) {
2982			--quo;
2983			rem += div;
2984		    }
2985		}
2986		else {
2987		    if (rem <= (div - 1) / 2) {
2988			++quo;
2989			rem -= div;
2990		    }
2991		}
2992	    }
2993	    break;
2994    }
2995
2996    NITYPE(num) = N_FIXNUM;
2997    NIFI(num) = rem;
2998    if (flo) {
2999	NRTYPE(num) = N_FLONUM;
3000	NRFF(num) = (double)quo;
3001    }
3002    else
3003	NRFI(num) = quo;
3004}
3005
3006static void
3007ndivide_xi_xi(n_number *num, LispObj *div, int fun, int flo)
3008{
3009    LispType type = OBJECT_TYPE(div);
3010    int state = NDIVIDE_NOP, dsign, rsign;
3011    mpi *quo, *rem;
3012
3013    quo = XALLOC(mpi);
3014    mpi_init(quo);
3015    if (NRTYPE(num) == N_FIXNUM)
3016	mpi_seti(quo, NRFI(num));
3017    else
3018	mpi_set(quo, NRBI(num));
3019
3020    rem = XALLOC(mpi);
3021    mpi_init(rem);
3022
3023    switch (type) {
3024	case LispFixnum_t:
3025	    mpi_seti(rem, OFI(div));
3026	    break;
3027	case LispInteger_t:
3028	    mpi_seti(rem, OII(div));
3029	    break;
3030	default:
3031	    mpi_set(rem, OBI(div));
3032    }
3033
3034    dsign = mpi_sgn(rem);
3035
3036    mpi_divqr(quo, rem, quo, rem);
3037    rsign = mpi_sgn(rem);
3038
3039    switch (fun) {
3040	case NDIVIDE_CEIL:
3041	    if ((rsign < 0 && dsign < 0) || (rsign > 0 && dsign > 0))
3042		state = NDIVIDE_ADD;
3043	    break;
3044	case NDIVIDE_FLOOR:
3045	    if ((rsign < 0 && dsign > 0) || (rsign > 0 && dsign < 0))
3046		state = NDIVIDE_SUB;
3047	    break;
3048	case NDIVIDE_ROUND: {
3049	    mpi test;
3050
3051	    mpi_init(&test);
3052	    switch (type) {
3053		case LispFixnum_t:
3054		    mpi_seti(&test, OFI(div));
3055		    break;
3056		case LispInteger_t:
3057		    mpi_seti(&test, OII(div));
3058		    break;
3059		default:
3060		    mpi_set(&test, OBI(div));
3061	    }
3062	    if (dsign > 0) {
3063		if (rsign > 0) {
3064		    mpi_addi(&test, &test, 1);
3065		    mpi_divi(&test, &test, 2);
3066		    if (mpi_cmp(rem, &test) >= 0)
3067			state = NDIVIDE_ADD;
3068		}
3069		else {
3070		    mpi_neg(&test, &test);
3071		    mpi_subi(&test, &test, 1);
3072		    mpi_divi(&test, &test, 2);
3073		    if (mpi_cmp(rem, &test) <= 0)
3074			state = NDIVIDE_SUB;
3075		}
3076	    }
3077	    else {
3078		if (rsign > 0) {
3079		    mpi_neg(&test, &test);
3080		    mpi_addi(&test, &test, 1);
3081		    mpi_divi(&test, &test, 2);
3082		    if (mpi_cmp(rem, &test) >= 0)
3083			state = NDIVIDE_SUB;
3084		}
3085		else {
3086		    mpi_subi(&test, &test, 1);
3087		    mpi_divi(&test, &test, 2);
3088		    if (mpi_cmp(rem, &test) <= 0)
3089			state = NDIVIDE_ADD;
3090		}
3091	    }
3092	    mpi_clear(&test);
3093	}   break;
3094    }
3095
3096    if (state == NDIVIDE_ADD) {
3097	mpi_addi(quo, quo, 1);
3098	switch (type) {
3099	    case LispFixnum_t:
3100		mpi_subi(rem, rem, OFI(div));
3101		break;
3102	    case LispInteger_t:
3103		mpi_subi(rem, rem, OII(div));
3104		break;
3105	    default:
3106		mpi_sub(rem, rem, OBI(div));
3107	}
3108    }
3109    else if (state == NDIVIDE_SUB) {
3110	mpi_subi(quo, quo, 1);
3111	switch (type) {
3112	    case LispFixnum_t:
3113		mpi_addi(rem, rem, OFI(div));
3114		break;
3115	    case LispInteger_t:
3116		mpi_addi(rem, rem, OII(div));
3117		break;
3118	    default:
3119		mpi_add(rem, rem, OBI(div));
3120	}
3121    }
3122
3123    if (mpi_fiti(rem)) {
3124	NITYPE(num) = N_FIXNUM;
3125	NIFI(num) = mpi_geti(rem);
3126	mpi_clear(rem);
3127	XFREE(rem);
3128    }
3129    else {
3130	NITYPE(num) = N_BIGNUM;
3131	NIBI(num) = rem;
3132    }
3133
3134    clear_real(NREAL(num));
3135
3136    if (flo) {
3137	double dval = bi_getd(quo);
3138
3139	mpi_clear(quo);
3140	XFREE(quo);
3141	NRTYPE(num) = N_FLONUM;
3142	NRFF(num) = dval;
3143    }
3144    else {
3145	NRTYPE(num) = N_BIGNUM;
3146	NRBI(num) = quo;
3147	rbi_canonicalize(NREAL(num));
3148    }
3149}
3150
3151static void
3152ndivide_flonum(n_number *number, double num, double div, int fun, int flo)
3153{
3154    double quo, rem, modp, tmp;
3155
3156    modp = modf(num / div, &quo);
3157    rem = num - quo * div;
3158
3159    switch (fun) {
3160	case NDIVIDE_CEIL:
3161	    if ((rem < 0.0 && div < 0.0) || (rem > 0.0 && div > 0.0)) {
3162		quo += 1.0;
3163		rem -= div;
3164	    }
3165	    break;
3166	case NDIVIDE_FLOOR:
3167	    if ((rem < 0.0 && div > 0.0) || (rem > 0.0 && div < 0.0)) {
3168		quo -= 1.0;
3169		rem += div;
3170	    }
3171	    break;
3172	case NDIVIDE_ROUND:
3173	    if (fabs(modp) != 0.5 || modf(quo * 0.5, &tmp) != 0.0) {
3174		if (div > 0.0) {
3175		    if (rem > 0.0) {
3176			if (rem >= div * 0.5) {
3177			    quo += 1.0;
3178			    rem -= div;
3179			}
3180		    }
3181		    else {
3182			if (rem <= div * -0.5) {
3183			    quo -= 1.0;
3184			    rem += div;
3185			}
3186		    }
3187		}
3188		else {
3189		    if (rem > 0.0) {
3190			if (rem >= div * -0.5) {
3191			    quo -= 1.0;
3192			    rem += div;
3193			}
3194		    }
3195		    else {
3196			if (rem <= div * 0.5) {
3197			    quo += 1.0;
3198			    rem -= div;
3199			}
3200		    }
3201		}
3202	    }
3203	    break;
3204    }
3205    if (!finite(quo) || !finite(rem))
3206	fatal_error(FLOATING_POINT_OVERFLOW);
3207
3208    NITYPE(number) = N_FLONUM;
3209    NIFF(number) = rem;
3210
3211    clear_real(NREAL(number));
3212
3213    if (flo) {
3214	NRTYPE(number) = N_FLONUM;
3215	NRFF(number) = quo;
3216    }
3217    else {
3218	if ((long)quo == quo) {
3219	    NRTYPE(number) = N_FIXNUM;
3220	    NRFI(number) = (long)quo;
3221	}
3222	else {
3223	    mpi *bigi = XALLOC(mpi);
3224
3225	    mpi_init(bigi);
3226	    mpi_setd(bigi, quo);
3227	    NRBI(number) = bigi;
3228	    NRTYPE(number) = N_BIGNUM;
3229	}
3230    }
3231}
3232
3233static void
3234ndivide_xi_xr(n_number *num, LispObj *div, int fun, int flo)
3235{
3236    int state = NDIVIDE_NOP, dsign, rsign;
3237    mpi *quo;
3238    mpr *rem;
3239
3240    quo = XALLOC(mpi);
3241    mpi_init(quo);
3242    if (NRTYPE(num) == N_FIXNUM)
3243	mpi_seti(quo, NRFI(num));
3244    else
3245	mpi_set(quo, NRBI(num));
3246
3247    rem = XALLOC(mpr);
3248    mpr_init(rem);
3249
3250    if (XOBJECT_TYPE(div) == LispRatio_t)
3251	mpr_seti(rem, OFRN(div), OFRD(div));
3252    else
3253	mpr_set(rem, OBR(div));
3254    dsign = mpi_sgn(mpr_num(rem));
3255    mpi_mul(quo, quo, mpr_den(rem));
3256
3257    mpi_divqr(quo, mpr_num(rem), quo, mpr_num(rem));
3258    mpr_canonicalize(rem);
3259
3260    rsign = mpi_sgn(mpr_num(rem));
3261    if (mpr_fiti(rem)) {
3262	if (mpi_geti(mpr_den(rem)) == 1) {
3263	    NITYPE(num) = N_FIXNUM;
3264	    NIFI(num) = mpi_geti(mpr_num(rem));
3265	}
3266	else {
3267	    NITYPE(num) = N_FIXRATIO;
3268	    NIFRN(num) = mpi_geti(mpr_num(rem));
3269	    NIFRD(num) = mpi_geti(mpr_den(rem));
3270	}
3271	mpr_clear(rem);
3272	XFREE(rem);
3273    }
3274    else {
3275	if (mpi_fiti(mpr_den(rem)) && mpi_geti(mpr_den(rem)) == 1) {
3276	    NITYPE(num) = N_BIGNUM;
3277	    NIBI(num) = mpr_num(rem);
3278	    mpi_clear(mpr_den(rem));
3279	    XFREE(rem);
3280	}
3281	else {
3282	    NITYPE(num) = N_BIGRATIO;
3283	    NIBR(num) = rem;
3284	}
3285    }
3286
3287    switch (fun) {
3288	case NDIVIDE_CEIL:
3289	    if ((rsign < 0 && dsign < 0) || (rsign > 0 && dsign > 0))
3290		state = NDIVIDE_ADD;
3291	    break;
3292	case NDIVIDE_FLOOR:
3293	    if ((rsign < 0 && dsign > 0) || (rsign > 0 && dsign < 0))
3294		state = NDIVIDE_SUB;
3295	    break;
3296	case NDIVIDE_ROUND: {
3297	    n_real cmp;
3298
3299	    set_real_object(&cmp, div);
3300	    div_real_real(&cmp, &two);
3301	    if (dsign > 0) {
3302		if (rsign > 0) {
3303		    if (cmp_real_real(NIMAG(num), &cmp) >= 0)
3304			state = NDIVIDE_ADD;
3305		}
3306		else {
3307		    neg_real(&cmp);
3308		    if (cmp_real_real(NIMAG(num), &cmp) <= 0)
3309			state = NDIVIDE_SUB;
3310		}
3311	    }
3312	    else {
3313		if (rsign > 0) {
3314		    neg_real(&cmp);
3315		    if (cmp_real_real(NIMAG(num), &cmp) >= 0)
3316			state = NDIVIDE_SUB;
3317		}
3318		else {
3319		    if (cmp_real_real(NIMAG(num), &cmp) <= 0)
3320			state = NDIVIDE_ADD;
3321		}
3322	    }
3323	    clear_real(&cmp);
3324	}   break;
3325    }
3326
3327    if (state == NDIVIDE_ADD) {
3328	mpi_addi(quo, quo, 1);
3329	sub_real_object(NIMAG(num), div);
3330    }
3331    else if (state == NDIVIDE_SUB) {
3332	mpi_subi(quo, quo, 1);
3333	add_real_object(NIMAG(num), div);
3334    }
3335
3336    clear_real(NREAL(num));
3337
3338    if (flo) {
3339	double dval = bi_getd(quo);
3340
3341	mpi_clear(quo);
3342	XFREE(quo);
3343	NRTYPE(num) = N_FLONUM;
3344	NRFF(num) = dval;
3345    }
3346    else {
3347	NRBI(num)  = quo;
3348	NRTYPE(num) = N_BIGNUM;
3349	rbi_canonicalize(NREAL(num));
3350    }
3351}
3352
3353static void
3354ndivide_xr_xi(n_number *num, LispObj *div, int fun, int flo)
3355{
3356    LispType type = OBJECT_TYPE(div);
3357    int state = NDIVIDE_NOP, dsign, rsign;
3358    mpi *quo;
3359    mpr *rem;
3360
3361    quo = XALLOC(mpi);
3362    mpi_init(quo);
3363    switch (type) {
3364	case LispFixnum_t:
3365	    dsign = OFI(div) < 0 ? -1 : OFI(div) > 0 ? 1 : 0;
3366	    mpi_seti(quo, OFI(div));
3367	    break;
3368	case LispInteger_t:
3369	    dsign = OII(div) < 0 ? -1 : OII(div) > 0 ? 1 : 0;
3370	    mpi_seti(quo, OII(div));
3371	    break;
3372	default:
3373	    dsign = mpi_sgn(OBI(div));
3374	    mpi_set(quo, OBI(div));
3375	    break;
3376    }
3377
3378    rem = XALLOC(mpr);
3379    mpr_init(rem);
3380    if (NRTYPE(num) == N_FIXRATIO) {
3381	mpr_seti(rem, NRFRN(num), NRFRD(num));
3382	mpi_muli(quo, quo, NRFRD(num));
3383    }
3384    else {
3385	mpr_set(rem, NRBR(num));
3386	mpi_mul(quo, quo, NRBRD(num));
3387    }
3388    mpi_divqr(quo, mpr_num(rem), mpr_num(rem), quo);
3389    mpr_canonicalize(rem);
3390
3391    rsign = mpi_sgn(mpr_num(rem));
3392    if (mpr_fiti(rem)) {
3393	NITYPE(num) = N_FIXRATIO;
3394	NIFRN(num) = mpi_geti(mpr_num(rem));
3395	NIFRD(num) = mpi_geti(mpr_den(rem));
3396	mpr_clear(rem);
3397	XFREE(rem);
3398    }
3399    else {
3400	NITYPE(num) = N_BIGRATIO;
3401	NIBR(num) = rem;
3402    }
3403
3404    switch (fun) {
3405	case NDIVIDE_CEIL:
3406	    if ((rsign < 0 && dsign < 0) || (rsign > 0 && dsign > 0))
3407		state = NDIVIDE_ADD;
3408	    break;
3409	case NDIVIDE_FLOOR:
3410	    if ((rsign < 0 && dsign > 0) || (rsign > 0 && dsign < 0))
3411		state = NDIVIDE_SUB;
3412	    break;
3413	case NDIVIDE_ROUND: {
3414	    n_real cmp;
3415
3416	    set_real_object(&cmp, div);
3417	    div_real_real(&cmp, &two);
3418	    if (dsign > 0) {
3419		if (rsign > 0) {
3420		    if (cmp_real_real(NIMAG(num), &cmp) >= 0)
3421			state = NDIVIDE_ADD;
3422		}
3423		else {
3424		    neg_real(&cmp);
3425		    if (cmp_real_real(NIMAG(num), &cmp) <= 0)
3426			state = NDIVIDE_SUB;
3427		}
3428	    }
3429	    else {
3430		if (rsign > 0) {
3431		    neg_real(&cmp);
3432		    if (cmp_real_real(NIMAG(num), &cmp) >= 0)
3433			state = NDIVIDE_SUB;
3434		}
3435		else {
3436		    if (cmp_real_real(NIMAG(num), &cmp) <= 0)
3437			state = NDIVIDE_ADD;
3438		}
3439	    }
3440	    clear_real(&cmp);
3441	}   break;
3442    }
3443
3444    if (state == NDIVIDE_ADD) {
3445	mpi_addi(quo, quo, 1);
3446	sub_real_object(NIMAG(num), div);
3447    }
3448    else if (state == NDIVIDE_SUB) {
3449	mpi_subi(quo, quo, 1);
3450	add_real_object(NIMAG(num), div);
3451    }
3452
3453    clear_real(NREAL(num));
3454
3455    if (flo) {
3456	double dval = bi_getd(quo);
3457
3458	mpi_clear(quo);
3459	XFREE(quo);
3460	NRTYPE(num) = N_FLONUM;
3461	NRFF(num) = dval;
3462    }
3463    else {
3464	NRBI(num) = quo;
3465	NRTYPE(num) = N_BIGNUM;
3466	rbi_canonicalize(NREAL(num));
3467    }
3468}
3469
3470static void
3471ndivide_xr_xr(n_number *num, LispObj *div, int fun, int flo)
3472{
3473    int state = NDIVIDE_NOP, dsign, rsign, modp;
3474    mpr *bigr;
3475    mpi *bigi;
3476
3477    bigr = XALLOC(mpr);
3478    mpr_init(bigr);
3479    if (NRTYPE(num) == N_FIXRATIO)
3480	mpr_seti(bigr, NRFRN(num), NRFRD(num));
3481    else
3482	mpr_set(bigr, NRBR(num));
3483
3484    NITYPE(num) = N_BIGRATIO;
3485    NIBR(num) = bigr;
3486
3487    if (OBJECT_TYPE(div) == LispRatio_t) {
3488	dsign = OFRN(div) < 0 ? -1 : OFRN(div) > 0 ? 1 : 0;
3489	mpi_muli(mpr_num(bigr), mpr_num(bigr), OFRD(div));
3490	mpi_muli(mpr_den(bigr), mpr_den(bigr), OFRN(div));
3491    }
3492    else {
3493	dsign = mpi_sgn(OBRN(div));
3494	mpr_div(bigr, bigr, OBR(div));
3495    }
3496    modp = mpi_fiti(mpr_den(bigr)) && mpi_geti(mpr_den(bigr)) == 2;
3497
3498    bigi = XALLOC(mpi);
3499    mpi_init(bigi);
3500    mpi_divqr(bigi, mpr_num(bigr), mpr_num(bigr), mpr_den(bigr));
3501
3502    if (OBJECT_TYPE(div) == LispRatio_t)
3503	mpi_seti(mpr_den(bigr), OFRD(div));
3504    else
3505	mpi_set(mpr_den(bigr), OBRD(div));
3506    if (NRTYPE(num) == N_FIXRATIO)
3507	mpi_muli(mpr_den(bigr), mpr_den(bigr), NRFRD(num));
3508    else
3509	mpi_mul(mpr_den(bigr), mpr_den(bigr), NRBRD(num));
3510
3511    clear_real(NREAL(num));
3512    NRTYPE(num) = N_BIGNUM;
3513    NRBI(num) = bigi;
3514
3515    rbr_canonicalize(NIMAG(num));
3516    rsign = cmp_real_real(NIMAG(num), &zero);
3517
3518    switch (fun) {
3519	case NDIVIDE_CEIL:
3520	    if ((rsign < 0 && dsign < 0) || (rsign > 0 && dsign > 0))
3521		state = NDIVIDE_ADD;
3522	    break;
3523	case NDIVIDE_FLOOR:
3524	    if ((rsign < 0 && dsign > 0) || (rsign > 0 && dsign < 0))
3525		state = NDIVIDE_SUB;
3526	    break;
3527	case NDIVIDE_ROUND:
3528	    if (!modp || (bigi->digs[0] & 1) == 1) {
3529		n_real cmp;
3530
3531		set_real_object(&cmp, div);
3532		div_real_real(&cmp, &two);
3533		if (dsign > 0) {
3534		    if (rsign > 0) {
3535			if (cmp_real_real(NIMAG(num), &cmp) >= 0)
3536			    state = NDIVIDE_ADD;
3537		    }
3538		    else {
3539			neg_real(&cmp);
3540			if (cmp_real_real(NIMAG(num), &cmp) <= 0)
3541			    state = NDIVIDE_SUB;
3542		    }
3543		}
3544		else {
3545		    if (rsign > 0) {
3546			neg_real(&cmp);
3547			if (cmp_real_real(NIMAG(num), &cmp) >= 0)
3548			    state = NDIVIDE_SUB;
3549		    }
3550		    else {
3551			if (cmp_real_real(NIMAG(num), &cmp) <= 0)
3552			    state = NDIVIDE_ADD;
3553		    }
3554		}
3555		clear_real(&cmp);
3556	    }
3557	    break;
3558    }
3559
3560    if (state == NDIVIDE_ADD) {
3561	add_real_real(NREAL(num), &one);
3562	sub_real_object(NIMAG(num), div);
3563    }
3564    else if (state == NDIVIDE_SUB) {
3565	sub_real_real(NREAL(num), &one);
3566	add_real_object(NIMAG(num), div);
3567    }
3568
3569    if (NRTYPE(num) == N_BIGNUM) {
3570	if (flo) {
3571	    double dval = bi_getd(bigi);
3572
3573	    mpi_clear(bigi);
3574	    XFREE(bigi);
3575	    NRTYPE(num) = N_FLONUM;
3576	    NRFF(num) = dval;
3577	}
3578	else
3579	    rbi_canonicalize(NREAL(num));
3580    }
3581    else if (flo) {
3582	NRTYPE(num) = N_FLONUM;
3583	NRFF(num) = (double)NRFI(num);
3584    }
3585}
3586
3587
3588/************************************************************************
3589 * REAL COMPLEX
3590 ************************************************************************/
3591static void
3592nadd_re_cx(n_number *num, LispObj *comp)
3593{
3594/*
3595	Ra+Rb Ib
3596 */
3597    /* Ra+Rb */
3598    add_real_object(NREAL(num), OCXR(comp));
3599
3600    /* Ib */
3601    set_real_object(NIMAG(num), OCXI(comp));
3602
3603    num->complex = 1;
3604
3605    ncx_canonicalize(num);
3606}
3607
3608static void
3609nsub_re_cx(n_number *num, LispObj *comp)
3610{
3611/*
3612	Ra-Rb -Ib
3613 */
3614    /* Ra-Rb */
3615    sub_real_object(NREAL(num), OCXR(comp));
3616
3617    /* -Ib */
3618    NITYPE(num) = N_FIXNUM;
3619    NIFI(num) = -1;
3620    mul_real_object(NIMAG(num), OCXI(comp));
3621
3622    num->complex = 1;
3623
3624    ncx_canonicalize(num);
3625}
3626
3627static void
3628nmul_re_cx(n_number *num, LispObj *comp)
3629{
3630/*
3631	Ra*Rb Ra*Ib
3632 */
3633    /* copy before change */
3634    set_real_real(NIMAG(num), NREAL(num));
3635
3636    /* Ra*Rb */
3637    mul_real_object(NREAL(num), OCXR(comp));
3638
3639    /* Ra*Ib */
3640    mul_real_object(NIMAG(num), OCXI(comp));
3641
3642    num->complex = 1;
3643
3644    ncx_canonicalize(num);
3645}
3646
3647static void
3648ndiv_re_cx(n_number *num, LispObj *comp)
3649{
3650/*
3651	Ra*Rb        -Ib*Ra
3652	-----------  -----------
3653	Rb*Rb+Ib*Ib  Rb*Rb+Ib*Ib
3654 */
3655    n_real div, temp;
3656
3657    /* Rb*Rb */
3658    set_real_object(&div, OCXR(comp));
3659    mul_real_object(&div, OCXR(comp));
3660
3661    /* Ib*Ib */
3662    set_real_object(&temp, OCXI(comp));
3663    mul_real_object(&temp, OCXI(comp));
3664
3665    /* Rb*Rb+Ib*Ib */
3666    add_real_real(&div, &temp);
3667    clear_real(&temp);
3668
3669    /* -Ib*Ra */
3670    NITYPE(num) = N_FIXNUM;
3671    NIFI(num) = -1;
3672    mul_real_object(NIMAG(num), OCXI(comp));
3673    mul_real_real(NIMAG(num), NREAL(num));
3674
3675    /* Ra*Rb */
3676    mul_real_object(NREAL(num), OCXR(comp));
3677
3678    div_real_real(NREAL(num), &div);
3679    div_real_real(NIMAG(num), &div);
3680    clear_real(&div);
3681
3682    num->complex = 1;
3683
3684    ncx_canonicalize(num);
3685}
3686
3687
3688/************************************************************************
3689 * COMPLEX REAL
3690 ************************************************************************/
3691static void
3692nadd_cx_re(n_number *num, LispObj *re)
3693{
3694/*
3695	Ra+Rb Ia
3696 */
3697    add_real_object(NREAL(num), re);
3698
3699    ncx_canonicalize(num);
3700}
3701
3702static void
3703nsub_cx_re(n_number *num, LispObj *re)
3704{
3705/*
3706	Ra-Rb Ia
3707 */
3708    sub_real_object(NREAL(num), re);
3709
3710    ncx_canonicalize(num);
3711}
3712
3713static void
3714nmul_cx_re(n_number *num, LispObj *re)
3715{
3716/*
3717	Ra*Rb Ia*Rb
3718 */
3719    mul_real_object(NREAL(num), re);
3720    mul_real_object(NIMAG(num), re);
3721
3722    ncx_canonicalize(num);
3723}
3724
3725static void
3726ndiv_cx_re(n_number *num, LispObj *re)
3727{
3728/*
3729	Ra/Rb Ia/Rb
3730 */
3731    div_real_object(NREAL(num), re);
3732    div_real_object(NIMAG(num), re);
3733
3734    ncx_canonicalize(num);
3735}
3736
3737
3738/************************************************************************
3739 * COMPLEX COMPLEX
3740 ************************************************************************/
3741static void
3742nadd_cx_cx(n_number *num, LispObj *comp)
3743{
3744/*
3745	Ra+Rb Ia+Ib
3746 */
3747    add_real_object(NREAL(num), OCXR(comp));
3748    add_real_object(NIMAG(num), OCXI(comp));
3749
3750    ncx_canonicalize(num);
3751}
3752
3753static void
3754nsub_cx_cx(n_number *num, LispObj *comp)
3755{
3756/*
3757	Ra-Rb Ia-Ib
3758 */
3759    sub_real_object(NREAL(num), OCXR(comp));
3760    sub_real_object(NIMAG(num), OCXI(comp));
3761
3762    ncx_canonicalize(num);
3763}
3764
3765static void
3766nmul_cx_cx(n_number *num, LispObj *comp)
3767{
3768/*
3769	Ra*Rb-Ia*Ib Ra*Ib+Ia*Rb
3770 */
3771    n_real IaIb, RaIb;
3772
3773    set_real_real(&IaIb, NIMAG(num));
3774    mul_real_object(&IaIb, OCXI(comp));
3775
3776    set_real_real(&RaIb, NREAL(num));
3777    mul_real_object(&RaIb, OCXI(comp));
3778
3779    /* Ra*Rb-Ia*Ib */
3780    mul_real_object(NREAL(num), OCXR(comp));
3781    sub_real_real(NREAL(num), &IaIb);
3782    clear_real(&IaIb);
3783
3784    /* Ra*Ib+Ia*Rb */
3785    mul_real_object(NIMAG(num), OCXR(comp));
3786    add_real_real(NIMAG(num), &RaIb);
3787    clear_real(&RaIb);
3788
3789    ncx_canonicalize(num);
3790}
3791
3792static void
3793ndiv_cx_cx(n_number *num, LispObj *comp)
3794{
3795/*
3796	Ra*Rb+Ia*Ib  Ia*Rb-Ib*Ra
3797	-----------  -----------
3798	Rb*Rb+Ib*Ib  Rb*Rb+Ib*Ib
3799 */
3800    n_real temp1, temp2;
3801
3802    /* IaIb */
3803    set_real_real(&temp1, NIMAG(num));
3804    mul_real_object(&temp1, OCXI(comp));
3805
3806    /* IbRa */
3807    set_real_real(&temp2, NREAL(num));
3808    mul_real_object(&temp2, OCXI(comp));
3809
3810    /* Ra*Rb+Ia*Ib */
3811    mul_real_object(NREAL(num), OCXR(comp));
3812    add_real_real(NREAL(num), &temp1);
3813    clear_real(&temp1);
3814
3815    /* Ia*Rb-Ib*Ra */
3816    mul_real_object(NIMAG(num), OCXR(comp));
3817    sub_real_real(NIMAG(num), &temp2);
3818    clear_real(&temp2);
3819
3820
3821    /* Rb*Rb */
3822    set_real_object(&temp1, OCXR(comp));
3823    mul_real_object(&temp1, OCXR(comp));
3824
3825    /* Ib*Ib */
3826    set_real_object(&temp2, OCXI(comp));
3827    mul_real_object(&temp2, OCXI(comp));
3828
3829    /* Rb*Rb+Ib*Ib */
3830    add_real_real(&temp1, &temp2);
3831    clear_real(&temp2);
3832
3833    div_real_real(NREAL(num), &temp1);
3834    div_real_real(NIMAG(num), &temp1);
3835    clear_real(&temp1);
3836
3837    ncx_canonicalize(num);
3838}
3839
3840static int
3841cmp_cx_cx(LispObj *op1, LispObj *op2)
3842{
3843    int cmp;
3844
3845    cmp = cmp_object_object(OCXR(op1), OCXR(op2), 1);
3846    if (cmp == 0)
3847	cmp = cmp_object_object(OCXI(op1), OCXI(op2), 1);
3848
3849    return (cmp);
3850}
3851
3852
3853/************************************************************************
3854 * FLONUM FLONUM
3855 ************************************************************************/
3856static void
3857radd_flonum(n_real *real, double op1, double op2)
3858{
3859    double value = op1 + op2;
3860
3861    if (!finite(value))
3862	fatal_error(FLOATING_POINT_OVERFLOW);
3863    switch (RTYPE(real)) {
3864	case N_FIXNUM:
3865	case N_FIXRATIO:
3866	    RTYPE(real) = N_FLONUM;
3867	    break;
3868	case N_BIGNUM:
3869	    RCLEAR_BI(real);
3870	    RTYPE(real) = N_FLONUM;
3871	    break;
3872	case N_BIGRATIO:
3873	    RCLEAR_BR(real);
3874	    RTYPE(real) = N_FLONUM;
3875	    break;
3876    }
3877    RFF(real) = value;
3878}
3879
3880static void
3881rsub_flonum(n_real *real, double op1, double op2)
3882{
3883    double value = op1 - op2;
3884
3885    if (!finite(value))
3886	fatal_error(FLOATING_POINT_OVERFLOW);
3887    switch (RTYPE(real)) {
3888	case N_FIXNUM:
3889	case N_FIXRATIO:
3890	    RTYPE(real) = N_FLONUM;
3891	    break;
3892	case N_BIGNUM:
3893	    RCLEAR_BI(real);
3894	    RTYPE(real) = N_FLONUM;
3895	    break;
3896	case N_BIGRATIO:
3897	    RCLEAR_BR(real);
3898	    RTYPE(real) = N_FLONUM;
3899	    break;
3900    }
3901    RFF(real) = value;
3902}
3903
3904static void
3905rmul_flonum(n_real *real, double op1, double op2)
3906{
3907    double value = op1 * op2;
3908
3909    if (!finite(value))
3910	fatal_error(FLOATING_POINT_OVERFLOW);
3911    switch (RTYPE(real)) {
3912	case N_FIXNUM:
3913	case N_FIXRATIO:
3914	    RTYPE(real) = N_FLONUM;
3915	    break;
3916	case N_BIGNUM:
3917	    RCLEAR_BI(real);
3918	    RTYPE(real) = N_FLONUM;
3919	    break;
3920	case N_BIGRATIO:
3921	    RCLEAR_BR(real);
3922	    RTYPE(real) = N_FLONUM;
3923	    break;
3924    }
3925    RFF(real) = value;
3926}
3927
3928static void
3929rdiv_flonum(n_real *real, double op1, double op2)
3930{
3931    double value;
3932
3933    if (op2 == 0.0)
3934	fatal_error(DIVIDE_BY_ZERO);
3935    value = op1 / op2;
3936    if (!finite(value))
3937	fatal_error(FLOATING_POINT_OVERFLOW);
3938    switch (RTYPE(real)) {
3939	case N_FIXNUM:
3940	case N_FIXRATIO:
3941	    RTYPE(real) = N_FLONUM;
3942	    break;
3943	case N_BIGNUM:
3944	    RCLEAR_BI(real);
3945	    RTYPE(real) = N_FLONUM;
3946	    break;
3947	case N_BIGRATIO:
3948	    RCLEAR_BR(real);
3949	    RTYPE(real) = N_FLONUM;
3950	    break;
3951    }
3952    RFF(real) = value;
3953}
3954
3955static int
3956cmp_flonum(double op1, double op2)
3957{
3958    double value = op1 - op2;
3959
3960    if (!finite(value))
3961	fatal_error(FLOATING_POINT_OVERFLOW);
3962
3963    return (value > 0.0 ? 1 : value < 0.0 ? -1 : 0);
3964}
3965
3966
3967/************************************************************************
3968 * FIXNUM FIXNUM
3969 ************************************************************************/
3970static void
3971rop_fi_fi_bi(n_real *real, long fi, int op)
3972{
3973    mpi *bigi = XALLOC(mpi);
3974
3975    mpi_init(bigi);
3976    mpi_seti(bigi, RFI(real));
3977    if (op == NOP_ADD)
3978	mpi_addi(bigi, bigi, fi);
3979    else if (op == NOP_SUB)
3980	mpi_subi(bigi, bigi, fi);
3981    else
3982	mpi_muli(bigi, bigi, fi);
3983    RBI(real) = bigi;
3984    RTYPE(real) = N_BIGNUM;
3985}
3986
3987static INLINE void
3988radd_fi_fi(n_real *real, long fi)
3989{
3990    if (!fi_fi_add_overflow(RFI(real), fi))
3991	RFI(real) += fi;
3992    else
3993	rop_fi_fi_bi(real, fi, NOP_ADD);
3994}
3995
3996static INLINE void
3997rsub_fi_fi(n_real *real, long fi)
3998{
3999    if (!fi_fi_sub_overflow(RFI(real), fi))
4000	RFI(real) -= fi;
4001    else
4002	rop_fi_fi_bi(real, fi, NOP_SUB);
4003}
4004
4005static INLINE void
4006rmul_fi_fi(n_real *real, long fi)
4007{
4008    if (!fi_fi_mul_overflow(RFI(real), fi))
4009	RFI(real) *= fi;
4010    else
4011	rop_fi_fi_bi(real, fi, NOP_MUL);
4012}
4013
4014static INLINE void
4015rdiv_fi_fi(n_real *real, long fi)
4016{
4017    RTYPE(real) = N_FIXRATIO;
4018    RFRN(real) = RFI(real);
4019    RFRD(real) = fi;
4020    rfr_canonicalize(real);
4021}
4022
4023static INLINE int
4024cmp_fi_fi(long op1, long op2)
4025{
4026    if (op1 > op2)
4027	return (1);
4028    else if (op1 < op2)
4029	return (-1);
4030
4031    return (0);
4032}
4033
4034
4035/************************************************************************
4036 * FIXNUM BIGNUM
4037 ************************************************************************/
4038static void
4039rop_fi_bi_xi(n_real *real, mpi *bi, int nop)
4040{
4041    mpi *bigi = XALLOC(mpi);
4042
4043    mpi_init(bigi);
4044    mpi_seti(bigi, RFI(real));
4045    if (nop == NOP_ADD)
4046	mpi_add(bigi, bigi, bi);
4047    else if (nop == NOP_SUB)
4048	mpi_sub(bigi, bigi, bi);
4049    else
4050	mpi_mul(bigi, bigi, bi);
4051
4052    if (mpi_fiti(bigi)) {
4053	RFI(real) = mpi_geti(bigi);
4054	mpi_clear(bigi);
4055	XFREE(bigi);
4056    }
4057    else {
4058	RBI(real) = bigi;
4059	RTYPE(real) = N_BIGNUM;
4060    }
4061}
4062
4063static INLINE void
4064radd_fi_bi(n_real *real, mpi *bi)
4065{
4066    rop_fi_bi_xi(real, bi, NOP_ADD);
4067}
4068
4069static INLINE void
4070rsub_fi_bi(n_real *real, mpi *bi)
4071{
4072    rop_fi_bi_xi(real, bi, NOP_SUB);
4073}
4074
4075static INLINE void
4076rmul_fi_bi(n_real *real, mpi *bi)
4077{
4078    rop_fi_bi_xi(real, bi, NOP_MUL);
4079}
4080
4081static void
4082rdiv_fi_bi(n_real *real, mpi *bi)
4083{
4084    mpr *bigr;
4085
4086    if (mpi_cmpi(bi, 0) == 0)
4087	fatal_error(DIVIDE_BY_ZERO);
4088
4089    bigr = XALLOC(mpr);
4090    mpr_init(bigr);
4091    mpi_seti(mpr_num(bigr), RFI(real));
4092    mpi_set(mpr_den(bigr), bi);
4093    RBR(real) = bigr;
4094    RTYPE(real) = N_BIGRATIO;
4095    rbr_canonicalize(real);
4096}
4097
4098static INLINE int
4099cmp_fi_bi(long fixnum, mpi *bignum)
4100{
4101    return (-mpi_cmpi(bignum, fixnum));
4102}
4103
4104
4105/************************************************************************
4106 * FIXNUM FIXRATIO
4107 ************************************************************************/
4108static void
4109rop_fi_fr_as_xr(n_real *real, long num, long den, int nop)
4110{
4111    int fit;
4112    long value = 0, op = RFI(real);
4113
4114    fit = !fi_fi_mul_overflow(op, den);
4115    if (fit) {
4116	value = op * den;
4117	if (nop == NOP_ADD)
4118	    fit = !fi_fi_add_overflow(value, num);
4119	else
4120	    fit = !fi_fi_sub_overflow(value, num);
4121    }
4122    if (fit) {
4123	if (nop == NOP_ADD)
4124	    RFRN(real) = value + num;
4125	else
4126	    RFRN(real) = value - num;
4127	RFRD(real) = den;
4128	RTYPE(real) = N_FIXRATIO;
4129	rfr_canonicalize(real);
4130    }
4131    else {
4132	mpi iop;
4133	mpr *bigr = XALLOC(mpr);
4134
4135	mpi_init(&iop);
4136	mpi_seti(&iop, op);
4137	mpi_muli(&iop, &iop, den);
4138
4139	mpr_init(bigr);
4140	mpr_seti(bigr, num, den);
4141	if (nop == NOP_ADD)
4142	    mpi_add(mpr_num(bigr), &iop, mpr_num(bigr));
4143	else
4144	    mpi_sub(mpr_num(bigr), &iop, mpr_num(bigr));
4145	mpi_clear(&iop);
4146	RBR(real) = bigr;
4147	RTYPE(real) = N_BIGRATIO;
4148	rbr_canonicalize(real);
4149    }
4150}
4151
4152static void
4153rop_fi_fr_md_xr(n_real *real, long num, long den, int nop)
4154{
4155    int fit;
4156    long op = RFI(real);
4157
4158    if (nop == NOP_MUL)
4159	fit = !fi_fi_mul_overflow(op, num);
4160    else
4161	fit = !fi_fi_mul_overflow(op, den);
4162    if (fit) {
4163	if (nop == NOP_MUL) {
4164	    RFRN(real) = op * num;
4165	    RFRD(real) = den;
4166	}
4167	else {
4168	    RFRN(real) = op * den;
4169	    RFRD(real) = num;
4170	}
4171	RTYPE(real) = N_FIXRATIO;
4172	rfr_canonicalize(real);
4173    }
4174    else {
4175	mpi iop;
4176	mpr *bigr = XALLOC(mpr);
4177
4178	mpi_init(&iop);
4179	mpi_seti(&iop, op);
4180
4181	mpr_init(bigr);
4182	if (nop == NOP_MUL)
4183	    mpr_seti(bigr, num, den);
4184	else
4185	    mpr_seti(bigr, den, num);
4186	mpi_mul(mpr_num(bigr), mpr_num(bigr), &iop);
4187	mpi_clear(&iop);
4188	RBR(real) = bigr;
4189	RTYPE(real) = N_BIGRATIO;
4190	rbr_canonicalize(real);
4191    }
4192}
4193
4194static INLINE void
4195radd_fi_fr(n_real *real, long num, long den)
4196{
4197    rop_fi_fr_as_xr(real, num, den, NOP_ADD);
4198}
4199
4200static INLINE void
4201rsub_fi_fr(n_real *real, long num, long den)
4202{
4203    rop_fi_fr_as_xr(real, num, den, NOP_SUB);
4204}
4205
4206static INLINE void
4207rmul_fi_fr(n_real *real, long num, long den)
4208{
4209    rop_fi_fr_md_xr(real, num, den, NOP_MUL);
4210}
4211
4212static INLINE void
4213rdiv_fi_fr(n_real *real, long num, long den)
4214{
4215    rop_fi_fr_md_xr(real, num, den, NOP_DIV);
4216}
4217
4218static INLINE int
4219cmp_fi_fr(long fi, long num, long den)
4220{
4221    return (cmp_flonum((double)fi, (double)num / (double)den));
4222}
4223
4224
4225/************************************************************************
4226 * FIXNUM BIGRATIO
4227 ************************************************************************/
4228static void
4229rop_fi_br_as_xr(n_real *real, mpr *ratio, int nop)
4230{
4231    mpi iop;
4232    mpr *bigr = XALLOC(mpr);
4233
4234    mpi_init(&iop);
4235    mpi_seti(&iop, RFI(real));
4236
4237    mpr_init(bigr);
4238    mpr_set(bigr, ratio);
4239
4240    mpi_mul(&iop, &iop, mpr_den(ratio));
4241    if (nop == NOP_ADD)
4242	mpi_add(mpr_num(bigr), &iop, mpr_num(bigr));
4243    else
4244	mpi_sub(mpr_num(bigr), &iop, mpr_num(bigr));
4245
4246    mpi_clear(&iop);
4247    RBR(real) = bigr;
4248    RTYPE(real) = N_BIGRATIO;
4249    rbr_canonicalize(real);
4250}
4251
4252static void
4253rop_fi_br_md_xr(n_real *real, mpr *ratio, int nop)
4254{
4255    mpi iop;
4256    mpr *bigr = XALLOC(mpr);
4257
4258    mpi_init(&iop);
4259    mpi_seti(&iop, RFI(real));
4260
4261    mpr_init(bigr);
4262    if (nop == NOP_MUL)
4263	mpr_set(bigr, ratio);
4264    else
4265	mpr_inv(bigr, ratio);
4266
4267    mpi_mul(mpr_num(bigr), &iop, mpr_num(bigr));
4268
4269    mpi_clear(&iop);
4270    RBR(real) = bigr;
4271    RTYPE(real) = N_BIGRATIO;
4272    rbr_canonicalize(real);
4273}
4274
4275static INLINE void
4276radd_fi_br(n_real *real, mpr *ratio)
4277{
4278    rop_fi_br_as_xr(real, ratio, NOP_ADD);
4279}
4280
4281static INLINE void
4282rsub_fi_br(n_real *real, mpr *ratio)
4283{
4284    rop_fi_br_as_xr(real, ratio, NOP_SUB);
4285}
4286
4287static INLINE void
4288rmul_fi_br(n_real *real, mpr *ratio)
4289{
4290    rop_fi_br_md_xr(real, ratio, NOP_MUL);
4291}
4292
4293static INLINE void
4294rdiv_fi_br(n_real *real, mpr *ratio)
4295{
4296    rop_fi_br_md_xr(real, ratio, NOP_DIV);
4297}
4298
4299static INLINE int
4300cmp_fi_br(long op1, mpr *op2)
4301{
4302    return (-mpr_cmpi(op2, op1));
4303}
4304
4305
4306/************************************************************************
4307 * BIGNUM FIXNUM
4308 ************************************************************************/
4309static INLINE void
4310radd_bi_fi(n_real *real, long fi)
4311{
4312    mpi_addi(RBI(real), RBI(real), fi);
4313    rbi_canonicalize(real);
4314}
4315
4316static INLINE void
4317rsub_bi_fi(n_real *real, long fi)
4318{
4319    mpi_subi(RBI(real), RBI(real), fi);
4320    rbi_canonicalize(real);
4321}
4322
4323static INLINE void
4324rmul_bi_fi(n_real *real, long fi)
4325{
4326    mpi_muli(RBI(real), RBI(real), fi);
4327    rbi_canonicalize(real);
4328}
4329
4330static void
4331rdiv_bi_fi(n_real *real, long fi)
4332{
4333    mpr *bigr;
4334
4335    if (RFI(real) == 0)
4336	fatal_error(DIVIDE_BY_ZERO);
4337
4338    bigr = XALLOC(mpr);
4339    mpr_init(bigr);
4340    mpi_set(mpr_num(bigr), RBI(real));
4341    mpi_seti(mpr_den(bigr), fi);
4342    RCLEAR_BI(real);
4343    RBR(real) = bigr;
4344    RTYPE(real) = N_BIGRATIO;
4345    rbr_canonicalize(real);
4346}
4347
4348static INLINE int
4349cmp_bi_fi(mpi *bignum, long fi)
4350{
4351    return (mpi_cmpi(bignum, fi));
4352}
4353
4354
4355/************************************************************************
4356 * BIGNUM BIGNUM
4357 ************************************************************************/
4358static INLINE void
4359radd_bi_bi(n_real *real, mpi *bignum)
4360{
4361    mpi_add(RBI(real), RBI(real), bignum);
4362    rbi_canonicalize(real);
4363}
4364
4365static INLINE void
4366rsub_bi_bi(n_real *real, mpi *bignum)
4367{
4368    mpi_sub(RBI(real), RBI(real), bignum);
4369    rbi_canonicalize(real);
4370}
4371
4372static INLINE void
4373rmul_bi_bi(n_real *real, mpi *bignum)
4374{
4375    mpi_mul(RBI(real), RBI(real), bignum);
4376    rbi_canonicalize(real);
4377}
4378
4379static void
4380rdiv_bi_bi(n_real *real, mpi *bignum)
4381{
4382    mpr *bigr;
4383
4384    if (mpi_cmpi(bignum, 0) == 0)
4385	fatal_error(DIVIDE_BY_ZERO);
4386
4387    bigr = XALLOC(mpr);
4388    mpr_init(bigr);
4389    mpi_set(mpr_num(bigr), RBI(real));
4390    mpi_set(mpr_den(bigr), bignum);
4391    RCLEAR_BI(real);
4392    RBR(real) = bigr;
4393    RTYPE(real) = N_BIGRATIO;
4394    rbr_canonicalize(real);
4395}
4396
4397static INLINE int
4398cmp_bi_bi(mpi *op1, mpi *op2)
4399{
4400    return (mpi_cmp(op1, op2));
4401}
4402
4403
4404/************************************************************************
4405 * BIGNUM FIXRATIO
4406 ************************************************************************/
4407static void
4408rop_bi_fr_as_xr(n_real *real, long num, long den, int nop)
4409{
4410    mpi iop;
4411    mpr *bigr = XALLOC(mpr);
4412
4413    mpi_init(&iop);
4414    mpi_set(&iop, RBI(real));
4415    mpi_muli(&iop, &iop, den);
4416
4417    mpr_init(bigr);
4418    mpr_seti(bigr, num, den);
4419
4420    if (nop == NOP_ADD)
4421	mpi_add(mpr_num(bigr), &iop, mpr_num(bigr));
4422    else
4423	mpi_sub(mpr_num(bigr), &iop, mpr_num(bigr));
4424    mpi_clear(&iop);
4425
4426    RCLEAR_BI(real);
4427    RBR(real) = bigr;
4428    RTYPE(real) = N_BIGRATIO;
4429    rbr_canonicalize(real);
4430}
4431
4432static INLINE void
4433rop_bi_fr_md_xr(n_real *real, long num, long den, int nop)
4434{
4435    mpr *bigr = XALLOC(mpr);
4436
4437    mpr_init(bigr);
4438
4439    mpr_seti(bigr, num, den);
4440
4441    if (nop == NOP_MUL)
4442	mpi_mul(mpr_num(bigr), RBI(real), mpr_num(bigr));
4443    else {
4444	mpi_mul(mpr_den(bigr), RBI(real), mpr_den(bigr));
4445	mpr_inv(bigr, bigr);
4446    }
4447
4448    RCLEAR_BI(real);
4449    RBR(real) = bigr;
4450    RTYPE(real) = N_BIGRATIO;
4451    rbr_canonicalize(real);
4452}
4453
4454static INLINE void
4455radd_bi_fr(n_real *real, long num, long den)
4456{
4457    rop_bi_fr_as_xr(real, num, den, NOP_ADD);
4458}
4459
4460static INLINE void
4461rsub_bi_fr(n_real *real, long num, long den)
4462{
4463    rop_bi_fr_as_xr(real, num, den, NOP_SUB);
4464}
4465
4466static INLINE void
4467rmul_bi_fr(n_real *real, long num, long den)
4468{
4469    rop_bi_fr_md_xr(real, num, den, NOP_MUL);
4470}
4471
4472static INLINE void
4473rdiv_bi_fr(n_real *real, long num, long den)
4474{
4475    rop_bi_fr_md_xr(real, num, den, NOP_DIV);
4476}
4477
4478static int
4479cmp_bi_fr(mpi *bignum, long num, long den)
4480{
4481    int cmp;
4482    mpr cmp1, cmp2;
4483
4484    mpr_init(&cmp1);
4485    mpi_set(mpr_num(&cmp1), bignum);
4486    mpi_seti(mpr_den(&cmp1), 1);
4487
4488    mpr_init(&cmp2);
4489    mpr_seti(&cmp2, num, den);
4490
4491    cmp = mpr_cmp(&cmp1, &cmp2);
4492    mpr_clear(&cmp1);
4493    mpr_clear(&cmp2);
4494
4495    return (cmp);
4496}
4497
4498
4499/************************************************************************
4500 * BIGNUM BIGRATIO
4501 ************************************************************************/
4502static void
4503rop_bi_br_as_xr(n_real *real, mpr *bigratio, int nop)
4504{
4505    mpi iop;
4506    mpr *bigr = XALLOC(mpr);
4507
4508    mpi_init(&iop);
4509    mpi_set(&iop, RBI(real));
4510    mpr_init(bigr);
4511    mpr_set(bigr, bigratio);
4512
4513    mpi_mul(&iop, &iop, mpr_den(bigratio));
4514
4515    if (nop == NOP_ADD)
4516	mpi_add(mpr_num(bigr), &iop, mpr_num(bigr));
4517    else
4518	mpi_sub(mpr_num(bigr), &iop, mpr_num(bigr));
4519    mpi_clear(&iop);
4520
4521    RCLEAR_BI(real);
4522    RBR(real) = bigr;
4523    RTYPE(real) = N_BIGRATIO;
4524    rbr_canonicalize(real);
4525}
4526
4527static void
4528rop_bi_br_md_xr(n_real *real, mpr *bigratio, int nop)
4529{
4530    mpr *bigr = XALLOC(mpr);
4531
4532    mpr_init(bigr);
4533    if (nop == NOP_MUL)
4534	mpr_set(bigr, bigratio);
4535    else
4536	mpr_inv(bigr, bigratio);
4537
4538    mpi_mul(mpr_num(bigr), RBI(real), mpr_num(bigr));
4539
4540    RCLEAR_BI(real);
4541    RBR(real) = bigr;
4542    RTYPE(real) = N_BIGRATIO;
4543    rbr_canonicalize(real);
4544}
4545
4546static INLINE void
4547radd_bi_br(n_real *real, mpr *bigratio)
4548{
4549    rop_bi_br_as_xr(real, bigratio, NOP_ADD);
4550}
4551
4552static INLINE void
4553rsub_bi_br(n_real *real, mpr *bigratio)
4554{
4555    rop_bi_br_as_xr(real, bigratio, NOP_SUB);
4556}
4557
4558static INLINE void
4559rmul_bi_br(n_real *real, mpr *bigratio)
4560{
4561    rop_bi_br_md_xr(real, bigratio, NOP_MUL);
4562}
4563
4564static INLINE void
4565rdiv_bi_br(n_real *real, mpr *bigratio)
4566{
4567    rop_bi_br_md_xr(real, bigratio, NOP_DIV);
4568}
4569
4570static int
4571cmp_bi_br(mpi *bignum, mpr *bigratio)
4572{
4573    int cmp;
4574    mpr cmp1;
4575
4576    mpr_init(&cmp1);
4577    mpi_set(mpr_num(&cmp1), bignum);
4578    mpi_seti(mpr_den(&cmp1), 1);
4579
4580    cmp = mpr_cmp(&cmp1, bigratio);
4581    mpr_clear(&cmp1);
4582
4583    return (cmp);
4584}
4585
4586
4587/************************************************************************
4588 * FIXRATIO FIXNUM
4589 ************************************************************************/
4590static void
4591rop_fr_fi_as_xr(n_real *real, long op, int nop)
4592{
4593    int fit;
4594    long value = 0, num = RFRN(real), den = RFRD(real);
4595
4596    fit = !fi_fi_mul_overflow(op, den);
4597
4598    if (fit) {
4599	value = op * den;
4600	if (nop == NOP_ADD)
4601	    fit = !fi_fi_add_overflow(value, num);
4602	else
4603	    fit = !fi_fi_sub_overflow(value, num);
4604    }
4605    if (fit) {
4606	if (nop == NOP_ADD)
4607	    RFRN(real) = num + value;
4608	else
4609	    RFRN(real) = num - value;
4610	rfr_canonicalize(real);
4611    }
4612    else {
4613	mpi iop;
4614	mpr *bigr = XALLOC(mpr);
4615
4616	mpr_init(bigr);
4617	mpr_seti(bigr, num, den);
4618	mpi_init(&iop);
4619	mpi_seti(&iop, op);
4620	mpi_muli(&iop, &iop, den);
4621	if (nop == NOP_ADD)
4622	    mpi_add(mpr_num(bigr), mpr_num(bigr), &iop);
4623	else
4624	    mpi_sub(mpr_num(bigr), mpr_num(bigr), &iop);
4625	mpi_clear(&iop);
4626	RBR(real) = bigr;
4627	RTYPE(real) = N_BIGRATIO;
4628	rbr_canonicalize(real);
4629    }
4630}
4631
4632static void
4633rop_fr_fi_md_xr(n_real *real, long op, int nop)
4634{
4635    long num = RFRN(real), den = RFRD(real);
4636
4637    if (nop == NOP_MUL) {
4638	if (!fi_fi_mul_overflow(op, num)) {
4639	    RFRN(real) = op * num;
4640	    rfr_canonicalize(real);
4641	    return;
4642	}
4643    }
4644    else if (!fi_fi_mul_overflow(op, den)) {
4645	RFRD(real) = op * den;
4646	rfr_canonicalize(real);
4647	return;
4648    }
4649
4650    {
4651	mpr *bigr = XALLOC(mpr);
4652
4653	mpr_init(bigr);
4654	mpr_seti(bigr, num, den);
4655	if (nop == NOP_MUL)
4656	    mpr_muli(bigr, bigr, op);
4657	else
4658	    mpr_divi(bigr, bigr, op);
4659	RBR(real) = bigr;
4660	RTYPE(real) = N_BIGRATIO;
4661	rbr_canonicalize(real);
4662    }
4663}
4664
4665static INLINE void
4666radd_fr_fi(n_real *real, long op)
4667{
4668    rop_fr_fi_as_xr(real, op, NOP_ADD);
4669}
4670
4671static INLINE void
4672rsub_fr_fi(n_real *real, long op)
4673{
4674    rop_fr_fi_as_xr(real, op, NOP_SUB);
4675}
4676
4677static INLINE void
4678rmul_fr_fi(n_real *real, long op)
4679{
4680    rop_fr_fi_md_xr(real, op, NOP_MUL);
4681}
4682
4683static INLINE void
4684rdiv_fr_fi(n_real *real, long op)
4685{
4686    rop_fr_fi_md_xr(real, op, NOP_DIV);
4687}
4688
4689static INLINE int
4690cmp_fr_fi(long num, long den, long fixnum)
4691{
4692    return (cmp_flonum((double)num / (double)den, (double)fixnum));
4693}
4694
4695
4696/************************************************************************
4697 * FIXRATIO BIGNUM
4698 ************************************************************************/
4699static void
4700rop_fr_bi_as_xr(n_real *real, mpi *bignum, int nop)
4701{
4702    mpi iop;
4703    mpr *bigr = XALLOC(mpr);
4704
4705    mpr_init(bigr);
4706    mpr_seti(bigr, RFRN(real), RFRD(real));
4707
4708    mpi_init(&iop);
4709    mpi_set(&iop, bignum);
4710    mpi_muli(&iop, &iop, RFRD(real));
4711
4712    if (nop == NOP_ADD)
4713	mpi_add(mpr_num(bigr), mpr_num(bigr), &iop);
4714    else
4715	mpi_sub(mpr_num(bigr), mpr_num(bigr), &iop);
4716    mpi_clear(&iop);
4717
4718    RBR(real) = bigr;
4719    RTYPE(real) = N_BIGRATIO;
4720    rbr_canonicalize(real);
4721}
4722
4723static void
4724rop_fr_bi_md_xr(n_real *real, mpi *bignum, int nop)
4725{
4726    mpr *bigr = XALLOC(mpr);
4727
4728    mpr_init(bigr);
4729    mpr_seti(bigr, RFRN(real), RFRD(real));
4730
4731    if (nop == NOP_MUL)
4732	mpi_mul(mpr_num(bigr), mpr_num(bigr), bignum);
4733    else
4734	mpi_mul(mpr_den(bigr), mpr_den(bigr), bignum);
4735
4736    RBR(real) = bigr;
4737    RTYPE(real) = N_BIGRATIO;
4738    rbr_canonicalize(real);
4739}
4740
4741static INLINE void
4742radd_fr_bi(n_real *real, mpi *bignum)
4743{
4744    rop_fr_bi_as_xr(real, bignum, NOP_ADD);
4745}
4746
4747static INLINE void
4748rsub_fr_bi(n_real *real, mpi *bignum)
4749{
4750    rop_fr_bi_as_xr(real, bignum, NOP_SUB);
4751}
4752
4753static INLINE void
4754rmul_fr_bi(n_real *real, mpi *bignum)
4755{
4756    rop_fr_bi_md_xr(real, bignum, NOP_MUL);
4757}
4758
4759static INLINE void
4760rdiv_fr_bi(n_real *real, mpi *bignum)
4761{
4762    rop_fr_bi_md_xr(real, bignum, NOP_DIV);
4763}
4764
4765static int
4766cmp_fr_bi(long num, long den, mpi *bignum)
4767{
4768    int cmp;
4769    mpr cmp1, cmp2;
4770
4771    mpr_init(&cmp1);
4772    mpr_seti(&cmp1, num, den);
4773
4774    mpr_init(&cmp2);
4775    mpi_set(mpr_num(&cmp2), bignum);
4776    mpi_seti(mpr_den(&cmp2), 1);
4777
4778    cmp = mpr_cmp(&cmp1, &cmp2);
4779    mpr_clear(&cmp1);
4780    mpr_clear(&cmp2);
4781
4782    return (cmp);
4783}
4784
4785
4786/************************************************************************
4787 * FIXRATIO FIXRATIO
4788 ************************************************************************/
4789static void
4790rop_fr_fr_as_xr(n_real *real, long num2, long den2, int nop)
4791{
4792    int fit;
4793    long num1 = RFRN(real), den1 = RFRD(real), num = 0, den = 0;
4794
4795    fit = !fi_fi_mul_overflow(num1, den2);
4796    if (fit) {
4797	num = num1 * den2;
4798	fit = !fi_fi_mul_overflow(num2, den1);
4799	if (fit) {
4800	    den = num2 * den1;
4801	    if (nop == NOP_ADD) {
4802		if ((fit = !fi_fi_add_overflow(num, den)) != 0)
4803		    num += den;
4804	    }
4805	    else if ((fit = !fi_fi_sub_overflow(num, den)) != 0)
4806		num -= den;
4807	    if (fit) {
4808		fit = !fi_fi_mul_overflow(den1, den2);
4809		if (fit)
4810		    den = den1 * den2;
4811	    }
4812	}
4813    }
4814    if (fit) {
4815	RFRN(real) = num;
4816	RFRD(real) = den;
4817	rfr_canonicalize(real);
4818    }
4819    else {
4820	mpi iop;
4821	mpr *bigr = XALLOC(mpr);
4822
4823	mpr_init(bigr);
4824	mpr_seti(bigr, num1, den1);
4825	mpi_muli(mpr_den(bigr), mpr_den(bigr), den2);
4826	mpi_init(&iop);
4827	mpi_seti(&iop, num2);
4828	mpi_muli(&iop, &iop, den1);
4829	mpi_muli(mpr_num(bigr), mpr_num(bigr), den2);
4830	if (nop == NOP_ADD)
4831	    mpi_add(mpr_num(bigr), mpr_num(bigr), &iop);
4832	else
4833	    mpi_sub(mpr_num(bigr), mpr_num(bigr), &iop);
4834	mpi_clear(&iop);
4835	RBR(real) = bigr;
4836	RTYPE(real) = N_BIGRATIO;
4837	rbr_canonicalize(real);
4838    }
4839}
4840
4841static void
4842rop_fr_fr_md_xr(n_real *real, long num2, long den2, int nop)
4843{
4844    int fit;
4845    long num1 = RFRN(real), den1 = RFRD(real), num = 0, den = 0;
4846
4847    if (nop == NOP_MUL) {
4848	fit = !fi_fi_mul_overflow(num1, num2) && !fi_fi_mul_overflow(den1, den2);
4849	if (fit) {
4850	    num = num1 * num2;
4851	    den = den1 * den2;
4852	}
4853    }
4854    else {
4855	fit = !fi_fi_mul_overflow(num1, den2) && !fi_fi_mul_overflow(den1, num2);
4856	if (fit) {
4857	    num = num1 * den2;
4858	    den = den1 * num2;
4859	}
4860    }
4861
4862    if (fit) {
4863	RFRN(real) = num;
4864	RFRD(real) = den;
4865	rfr_canonicalize(real);
4866    }
4867    else {
4868	mpr *bigr = XALLOC(mpr);
4869
4870	mpr_init(bigr);
4871
4872	if (nop == NOP_MUL) {
4873	    mpr_seti(bigr, num1, den1);
4874	    mpi_muli(mpr_num(bigr), mpr_num(bigr), num2);
4875	    mpi_muli(mpr_den(bigr), mpr_den(bigr), den2);
4876	}
4877	else {
4878	    mpr_seti(bigr, num1, num2);
4879	    mpi_muli(mpr_num(bigr), mpr_num(bigr), den2);
4880	    mpi_muli(mpr_den(bigr), mpr_den(bigr), den1);
4881	}
4882
4883	RBR(real) = bigr;
4884	RTYPE(real) = N_BIGRATIO;
4885	rbr_canonicalize(real);
4886    }
4887}
4888
4889static INLINE void
4890radd_fr_fr(n_real *real, long num, long den)
4891{
4892    rop_fr_fr_as_xr(real, num, den, NOP_ADD);
4893}
4894
4895static INLINE void
4896rsub_fr_fr(n_real *real, long num, long den)
4897{
4898    rop_fr_fr_as_xr(real, num, den, NOP_SUB);
4899}
4900
4901static INLINE void
4902rmul_fr_fr(n_real *real, long num, long den)
4903{
4904    rop_fr_fr_md_xr(real, num, den, NOP_MUL);
4905}
4906
4907static INLINE void
4908rdiv_fr_fr(n_real *real, long num, long den)
4909{
4910    rop_fr_fr_md_xr(real, num, den, NOP_DIV);
4911}
4912
4913static INLINE int
4914cmp_fr_fr(long num1, long den1, long num2, long den2)
4915{
4916    return (cmp_flonum((double)num1 / (double)den1,
4917		       (double)num2 / (double)den2));
4918}
4919
4920
4921/************************************************************************
4922 * FIXRATIO BIGRATIO
4923 ************************************************************************/
4924static void
4925rop_fr_br_asmd_xr(n_real *real, mpr *bigratio, int nop)
4926{
4927    mpr *bigr = XALLOC(mpr);
4928
4929    mpr_init(bigr);
4930    mpr_seti(bigr, RFRN(real), RFRD(real));
4931
4932    switch (nop) {
4933	case NOP_ADD:
4934	    mpr_add(bigr, bigr, bigratio);
4935	    break;
4936	case NOP_SUB:
4937	    mpr_sub(bigr, bigr, bigratio);
4938	    break;
4939	case NOP_MUL:
4940	    mpr_mul(bigr, bigr, bigratio);
4941	    break;
4942	default:
4943	    mpr_div(bigr, bigr, bigratio);
4944	    break;
4945    }
4946
4947    RBR(real) = bigr;
4948    RTYPE(real) = N_BIGRATIO;
4949    rbr_canonicalize(real);
4950}
4951
4952static INLINE void
4953radd_fr_br(n_real *real, mpr *bigratio)
4954{
4955    rop_fr_br_asmd_xr(real, bigratio, NOP_ADD);
4956}
4957
4958static INLINE void
4959rsub_fr_br(n_real *real, mpr *bigratio)
4960{
4961    rop_fr_br_asmd_xr(real, bigratio, NOP_SUB);
4962}
4963
4964static INLINE void
4965rmul_fr_br(n_real *real, mpr *bigratio)
4966{
4967    rop_fr_br_asmd_xr(real, bigratio, NOP_MUL);
4968}
4969
4970static INLINE void
4971rdiv_fr_br(n_real *real, mpr *bigratio)
4972{
4973    rop_fr_br_asmd_xr(real, bigratio, NOP_DIV);
4974}
4975
4976static int
4977cmp_fr_br(long num, long den, mpr *bigratio)
4978{
4979    int cmp;
4980    mpr cmp1;
4981
4982    mpr_init(&cmp1);
4983    mpr_seti(&cmp1, num, den);
4984
4985    cmp = mpr_cmp(&cmp1, bigratio);
4986    mpr_clear(&cmp1);
4987
4988    return (cmp);
4989}
4990
4991
4992/************************************************************************
4993 * BIGRATIO FIXNUM
4994 ************************************************************************/
4995static void
4996rop_br_fi_asmd_xr(n_real *real, long fixnum, int nop)
4997{
4998    mpr *bigratio = RBR(real);
4999
5000    switch (nop) {
5001	case NOP_ADD:
5002	    mpr_addi(bigratio, bigratio, fixnum);
5003	    break;
5004	case NOP_SUB:
5005	    mpr_subi(bigratio, bigratio, fixnum);
5006	    break;
5007	case NOP_MUL:
5008	    mpr_muli(bigratio, bigratio, fixnum);
5009	    break;
5010	default:
5011	    if (fixnum == 0)
5012		fatal_error(DIVIDE_BY_ZERO);
5013	    mpr_divi(bigratio, bigratio, fixnum);
5014	    break;
5015    }
5016    rbr_canonicalize(real);
5017}
5018
5019static INLINE void
5020radd_br_fi(n_real *real, long fixnum)
5021{
5022    rop_br_fi_asmd_xr(real, fixnum, NOP_ADD);
5023}
5024
5025static INLINE void
5026rsub_br_fi(n_real *real, long fixnum)
5027{
5028    rop_br_fi_asmd_xr(real, fixnum, NOP_SUB);
5029}
5030
5031static INLINE void
5032rmul_br_fi(n_real *real, long fixnum)
5033{
5034    rop_br_fi_asmd_xr(real, fixnum, NOP_MUL);
5035}
5036
5037static INLINE void
5038rdiv_br_fi(n_real *real, long fixnum)
5039{
5040    rop_br_fi_asmd_xr(real, fixnum, NOP_DIV);
5041}
5042
5043static int
5044cmp_br_fi(mpr *bigratio, long fixnum)
5045{
5046    int cmp;
5047    mpr cmp2;
5048
5049    mpr_init(&cmp2);
5050    mpr_seti(&cmp2, fixnum, 1);
5051    cmp = mpr_cmp(bigratio, &cmp2);
5052    mpr_clear(&cmp2);
5053
5054    return (cmp);
5055}
5056
5057
5058/************************************************************************
5059 * BIGRATIO BIGNUM
5060 ************************************************************************/
5061static void
5062rop_br_bi_as_xr(n_real *real, mpi *bignum, int nop)
5063{
5064    mpi iop;
5065
5066    mpi_init(&iop);
5067    mpi_set(&iop, bignum);
5068
5069    mpi_mul(&iop, &iop, RBRD(real));
5070    if (nop == NOP_ADD)
5071	mpi_add(RBRN(real), RBRN(real), &iop);
5072    else
5073	mpi_sub(RBRN(real), RBRN(real), &iop);
5074    mpi_clear(&iop);
5075    rbr_canonicalize(real);
5076}
5077
5078static INLINE void
5079radd_br_bi(n_real *real, mpi *bignum)
5080{
5081    rop_br_bi_as_xr(real, bignum, NOP_ADD);
5082}
5083
5084static INLINE void
5085rsub_br_bi(n_real *real, mpi *bignum)
5086{
5087    rop_br_bi_as_xr(real, bignum, NOP_SUB);
5088}
5089
5090static INLINE void
5091rmul_br_bi(n_real *real, mpi *bignum)
5092{
5093    mpi_mul(RBRN(real), RBRN(real), bignum);
5094    rbr_canonicalize(real);
5095}
5096
5097static INLINE void
5098rdiv_br_bi(n_real *real, mpi *bignum)
5099{
5100    mpi_mul(RBRD(real), RBRD(real), bignum);
5101    rbr_canonicalize(real);
5102}
5103
5104static int
5105cmp_br_bi(mpr *bigratio, mpi *bignum)
5106{
5107    int cmp;
5108    mpr cmp1;
5109
5110    mpr_init(&cmp1);
5111    mpi_set(mpr_num(&cmp1), bignum);
5112    mpi_seti(mpr_den(&cmp1), 1);
5113
5114    cmp = mpr_cmp(bigratio, &cmp1);
5115    mpr_clear(&cmp1);
5116
5117    return (cmp);
5118}
5119
5120
5121/************************************************************************
5122 * BIGRATIO FIXRATIO
5123 ************************************************************************/
5124static void
5125rop_br_fr_asmd_xr(n_real *real, long num, long den, int nop)
5126{
5127    mpr *bigratio = RBR(real), rop;
5128
5129    mpr_init(&rop);
5130    mpr_seti(&rop, num, den);
5131    switch (nop) {
5132	case NOP_ADD:
5133	    mpr_add(bigratio, bigratio, &rop);
5134	    break;
5135	case NOP_SUB:
5136	    mpr_sub(bigratio, bigratio, &rop);
5137	    break;
5138	case NOP_MUL:
5139	    mpr_mul(bigratio, bigratio, &rop);
5140	    break;
5141	default:
5142	    mpr_div(bigratio, bigratio, &rop);
5143	    break;
5144    }
5145    mpr_clear(&rop);
5146    rbr_canonicalize(real);
5147}
5148
5149static INLINE void
5150radd_br_fr(n_real *real, long num, long den)
5151{
5152    rop_br_fr_asmd_xr(real, num, den, NOP_ADD);
5153}
5154
5155static INLINE void
5156rsub_br_fr(n_real *real, long num, long den)
5157{
5158    rop_br_fr_asmd_xr(real, num, den, NOP_SUB);
5159}
5160
5161static INLINE void
5162rmul_br_fr(n_real *real, long num, long den)
5163{
5164    rop_br_fr_asmd_xr(real, num, den, NOP_MUL);
5165}
5166
5167static INLINE void
5168rdiv_br_fr(n_real *real, long num, long den)
5169{
5170    rop_br_fr_asmd_xr(real, num, den, NOP_DIV);
5171}
5172
5173static int
5174cmp_br_fr(mpr *bigratio, long num, long den)
5175{
5176    int cmp;
5177    mpr cmp2;
5178
5179    mpr_init(&cmp2);
5180    mpr_seti(&cmp2, num, den);
5181    cmp = mpr_cmp(bigratio, &cmp2);
5182    mpr_clear(&cmp2);
5183
5184    return (cmp);
5185}
5186
5187
5188/************************************************************************
5189 * BIGRATIO BIGRATIO
5190 ************************************************************************/
5191static INLINE void
5192radd_br_br(n_real *real, mpr *bigratio)
5193{
5194    mpr_add(RBR(real), RBR(real), bigratio);
5195    rbr_canonicalize(real);
5196}
5197
5198static INLINE void
5199rsub_br_br(n_real *real, mpr *bigratio)
5200{
5201    mpr_sub(RBR(real), RBR(real), bigratio);
5202    rbr_canonicalize(real);
5203}
5204
5205static INLINE void
5206rmul_br_br(n_real *real, mpr *bigratio)
5207{
5208    mpr_mul(RBR(real), RBR(real), bigratio);
5209    rbr_canonicalize(real);
5210}
5211
5212static INLINE void
5213rdiv_br_br(n_real *real, mpr *bigratio)
5214{
5215    mpr_div(RBR(real), RBR(real), bigratio);
5216    rbr_canonicalize(real);
5217}
5218
5219static INLINE int
5220cmp_br_br(mpr *op1, mpr *op2)
5221{
5222    return (mpr_cmp(op1, op2));
5223}
5224