mathimp.c revision 5dfecf96
15dfecf96Smrg/*
25dfecf96Smrg * Copyright (c) 2002 by The XFree86 Project, Inc.
35dfecf96Smrg *
45dfecf96Smrg * Permission is hereby granted, free of charge, to any person obtaining a
55dfecf96Smrg * copy of this software and associated documentation files (the "Software"),
65dfecf96Smrg * to deal in the Software without restriction, including without limitation
75dfecf96Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
85dfecf96Smrg * and/or sell copies of the Software, and to permit persons to whom the
95dfecf96Smrg * Software is furnished to do so, subject to the following conditions:
105dfecf96Smrg *
115dfecf96Smrg * The above copyright notice and this permission notice shall be included in
125dfecf96Smrg * all copies or substantial portions of the Software.
135dfecf96Smrg *
145dfecf96Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
155dfecf96Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
165dfecf96Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
175dfecf96Smrg * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
185dfecf96Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
195dfecf96Smrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
205dfecf96Smrg * SOFTWARE.
215dfecf96Smrg *
225dfecf96Smrg * Except as contained in this notice, the name of the XFree86 Project shall
235dfecf96Smrg * not be used in advertising or otherwise to promote the sale, use or other
245dfecf96Smrg * dealings in this Software without prior written authorization from the
255dfecf96Smrg * XFree86 Project.
265dfecf96Smrg *
275dfecf96Smrg * Author: Paulo César Pereira de Andrade
285dfecf96Smrg */
295dfecf96Smrg
305dfecf96Smrg/* $XFree86: xc/programs/xedit/lisp/mathimp.c,v 1.14tsi Exp $ */
315dfecf96Smrg
325dfecf96Smrg
335dfecf96Smrg/*
345dfecf96Smrg * Defines
355dfecf96Smrg */
365dfecf96Smrg#ifdef __GNUC__
375dfecf96Smrg#define CONST			__attribute__ ((__const__))
385dfecf96Smrg#else
395dfecf96Smrg#define CONST			/**/
405dfecf96Smrg#endif
415dfecf96Smrg
425dfecf96Smrg/* mask for checking overflow on long operations */
435dfecf96Smrg#ifdef LONG64
445dfecf96Smrg#define FI_MASK			0x4000000000000000L
455dfecf96Smrg#define LONGSBITS		63
465dfecf96Smrg#else
475dfecf96Smrg#define FI_MASK			0x40000000L
485dfecf96Smrg#define LONGSBITS		31
495dfecf96Smrg#endif
505dfecf96Smrg
515dfecf96Smrg#define N_FIXNUM		1
525dfecf96Smrg#define N_BIGNUM		2
535dfecf96Smrg#define N_FLONUM		3
545dfecf96Smrg#define N_FIXRATIO		4
555dfecf96Smrg#define N_BIGRATIO		5
565dfecf96Smrg
575dfecf96Smrg#define NOP_ADD			1
585dfecf96Smrg#define NOP_SUB			2
595dfecf96Smrg#define NOP_MUL			3
605dfecf96Smrg#define NOP_DIV			4
615dfecf96Smrg
625dfecf96Smrg#define NDIVIDE_CEIL		1
635dfecf96Smrg#define NDIVIDE_FLOOR		2
645dfecf96Smrg#define NDIVIDE_ROUND		3
655dfecf96Smrg#define NDIVIDE_TRUNC		4
665dfecf96Smrg
675dfecf96Smrg/* real part from number */
685dfecf96Smrg#define NREAL(num)		&((num)->real)
695dfecf96Smrg#define NRTYPE(num)		(num)->real.type
705dfecf96Smrg#define NRFI(num)		(num)->real.data.fixnum
715dfecf96Smrg#define NRBI(num)		(num)->real.data.bignum
725dfecf96Smrg#define NRFF(num)		(num)->real.data.flonum
735dfecf96Smrg#define NRFRN(Num)		(Num)->real.data.fixratio.num
745dfecf96Smrg#define NRFRD(num)		(num)->real.data.fixratio.den
755dfecf96Smrg#define NRBR(num)		(num)->real.data.bigratio
765dfecf96Smrg#define NRBRN(num)		mpr_num(NRBR(num))
775dfecf96Smrg#define NRBRD(num)		mpr_den(NRBR(num))
785dfecf96Smrg
795dfecf96Smrg#define NRCLEAR_BI(num)		mpi_clear(NRBI(num)); XFREE(NRBI(num))
805dfecf96Smrg#define NRCLEAR_BR(num)		mpr_clear(NRBR(num)); XFREE(NRBR(num))
815dfecf96Smrg
825dfecf96Smrg/* imag part from number */
835dfecf96Smrg#define NIMAG(num)		&((num)->imag)
845dfecf96Smrg#define NITYPE(num)		(num)->imag.type
855dfecf96Smrg#define NIFI(num)		(num)->imag.data.fixnum
865dfecf96Smrg#define NIBI(num)		(num)->imag.data.bignum
875dfecf96Smrg#define NIFF(num)		(num)->imag.data.flonum
885dfecf96Smrg#define NIFRN(Num)		(Num)->imag.data.fixratio.num
895dfecf96Smrg#define NIFRD(num)		(num)->imag.data.fixratio.den
905dfecf96Smrg#define NIBR(num)		(num)->imag.data.bigratio
915dfecf96Smrg#define NIBRN(obj)		mpr_num(NIBR(obj))
925dfecf96Smrg#define NIBRD(obj)		mpr_den(NIBR(obj))
935dfecf96Smrg
945dfecf96Smrg/* real number fields */
955dfecf96Smrg#define RTYPE(real)		(real)->type
965dfecf96Smrg#define RFI(real)		(real)->data.fixnum
975dfecf96Smrg#define RBI(real)		(real)->data.bignum
985dfecf96Smrg#define RFF(real)		(real)->data.flonum
995dfecf96Smrg#define RFRN(real)		(real)->data.fixratio.num
1005dfecf96Smrg#define RFRD(real)		(real)->data.fixratio.den
1015dfecf96Smrg#define RBR(real)		(real)->data.bigratio
1025dfecf96Smrg#define RBRN(real)		mpr_num(RBR(real))
1035dfecf96Smrg#define RBRD(real)		mpr_den(RBR(real))
1045dfecf96Smrg
1055dfecf96Smrg#define RINTEGERP(real)				\
1065dfecf96Smrg    (RTYPE(real) == N_FIXNUM || RTYPE(real) == N_BIGNUM)
1075dfecf96Smrg
1085dfecf96Smrg#define RCLEAR_BI(real)		mpi_clear(RBI(real)); XFREE(RBI(real))
1095dfecf96Smrg#define RCLEAR_BR(real)		mpr_clear(RBR(real)); XFREE(RBR(real))
1105dfecf96Smrg
1115dfecf96Smrg/* numeric value from lisp object */
1125dfecf96Smrg#define OFI(object)		FIXNUM_VALUE(object)
1135dfecf96Smrg#define OII(object)		INT_VALUE(object)
1145dfecf96Smrg#define OBI(object)		(object)->data.mp.integer
1155dfecf96Smrg#define ODF(object)		DFLOAT_VALUE(object)
1165dfecf96Smrg#define OFRN(object)		(object)->data.ratio.numerator
1175dfecf96Smrg#define OFRD(object)		(object)->data.ratio.denominator
1185dfecf96Smrg#define OBR(object)		(object)->data.mp.ratio
1195dfecf96Smrg#define OBRN(object)		mpr_num(OBR(object))
1205dfecf96Smrg#define OBRD(object)		mpr_den(OBR(object))
1215dfecf96Smrg#define OCXR(object)		(object)->data.complex.real
1225dfecf96Smrg#define OCXI(object)		(object)->data.complex.imag
1235dfecf96Smrg
1245dfecf96Smrg#define XALLOC(type)		LispMalloc(sizeof(type))
1255dfecf96Smrg#define XFREE(ptr)		LispFree(ptr)
1265dfecf96Smrg
1275dfecf96Smrg
1285dfecf96Smrg/*
1295dfecf96Smrg * Types
1305dfecf96Smrg */
1315dfecf96Smrgtypedef struct _n_real {
1325dfecf96Smrg    char type;
1335dfecf96Smrg    union {
1345dfecf96Smrg	long fixnum;
1355dfecf96Smrg	mpi *bignum;
1365dfecf96Smrg	double flonum;
1375dfecf96Smrg	struct {
1385dfecf96Smrg	    long num;
1395dfecf96Smrg	    long den;
1405dfecf96Smrg	} fixratio;
1415dfecf96Smrg	mpr *bigratio;
1425dfecf96Smrg    } data;
1435dfecf96Smrg} n_real;
1445dfecf96Smrg
1455dfecf96Smrgtypedef struct _n_number {
1465dfecf96Smrg    char complex;
1475dfecf96Smrg    n_real real;
1485dfecf96Smrg    n_real imag;
1495dfecf96Smrg} n_number;
1505dfecf96Smrg
1515dfecf96Smrg
1525dfecf96Smrg/*
1535dfecf96Smrg * Prototypes
1545dfecf96Smrg */
1555dfecf96Smrgstatic void number_init(void);
1565dfecf96Smrgstatic LispObj *number_pi(void);
1575dfecf96Smrg
1585dfecf96Smrgstatic void set_real_real(n_real*, n_real*);
1595dfecf96Smrgstatic void set_real_object(n_real*, LispObj*);
1605dfecf96Smrgstatic void set_number_object(n_number*, LispObj*);
1615dfecf96Smrgstatic void clear_real(n_real*);
1625dfecf96Smrgstatic void clear_number(n_number*);
1635dfecf96Smrg
1645dfecf96Smrgstatic LispObj *make_real_object(n_real*);
1655dfecf96Smrgstatic LispObj *make_number_object(n_number*);
1665dfecf96Smrg
1675dfecf96Smrgstatic void fatal_error(int);
1685dfecf96Smrgstatic void fatal_object_error(LispObj*, int);
1695dfecf96Smrgstatic void fatal_builtin_object_error(LispBuiltin*, LispObj*, int);
1705dfecf96Smrg
1715dfecf96Smrgstatic double bi_getd(mpi*);
1725dfecf96Smrgstatic double br_getd(mpr*);
1735dfecf96Smrg
1745dfecf96Smrg/* add */
1755dfecf96Smrgstatic void add_real_object(n_real*, LispObj*);
1765dfecf96Smrgstatic void add_number_object(n_number*, LispObj*);
1775dfecf96Smrg
1785dfecf96Smrg/* sub */
1795dfecf96Smrgstatic void sub_real_object(n_real*, LispObj*);
1805dfecf96Smrgstatic void sub_number_object(n_number*, LispObj*);
1815dfecf96Smrg
1825dfecf96Smrg/* mul */
1835dfecf96Smrgstatic void mul_real_object(n_real*, LispObj*);
1845dfecf96Smrgstatic void mul_number_object(n_number*, LispObj*);
1855dfecf96Smrg
1865dfecf96Smrg/* div */
1875dfecf96Smrgstatic void div_real_object(n_real*, LispObj*);
1885dfecf96Smrgstatic void div_number_object(n_number*, LispObj*);
1895dfecf96Smrg
1905dfecf96Smrg/* compare */
1915dfecf96Smrgstatic int cmp_real_real(n_real*, n_real*);
1925dfecf96Smrgstatic int cmp_real_object(n_real*, LispObj*);
1935dfecf96Smrg#if 0	/* not used */
1945dfecf96Smrgstatic int cmp_number_object(n_number*, LispObj*);
1955dfecf96Smrg#endif
1965dfecf96Smrgstatic int cmp_object_object(LispObj*, LispObj*, int);
1975dfecf96Smrg
1985dfecf96Smrg/* fixnum */
1995dfecf96Smrgstatic INLINE int fi_fi_add_overflow(long, long) CONST;
2005dfecf96Smrgstatic INLINE int fi_fi_sub_overflow(long, long) CONST;
2015dfecf96Smrgstatic INLINE int fi_fi_mul_overflow(long, long) CONST;
2025dfecf96Smrg
2035dfecf96Smrg/* bignum */
2045dfecf96Smrgstatic void rbi_canonicalize(n_real*);
2055dfecf96Smrg
2065dfecf96Smrg/* ratio */
2075dfecf96Smrgstatic void rfr_canonicalize(n_real*);
2085dfecf96Smrgstatic void rbr_canonicalize(n_real*);
2095dfecf96Smrg
2105dfecf96Smrg/* complex */
2115dfecf96Smrgstatic void ncx_canonicalize(n_number*);
2125dfecf96Smrg
2135dfecf96Smrg/* abs */
2145dfecf96Smrgstatic void abs_real(n_real*);
2155dfecf96Smrgstatic void abs_number(n_number*);
2165dfecf96Smrgstatic void nabs_cx(n_number*);
2175dfecf96Smrgstatic INLINE void rabs_fi(n_real*);
2185dfecf96Smrgstatic INLINE void rabs_bi(n_real*);
2195dfecf96Smrgstatic INLINE void rabs_ff(n_real*);
2205dfecf96Smrgstatic INLINE void rabs_fr(n_real*);
2215dfecf96Smrgstatic INLINE void rabs_br(n_real*);
2225dfecf96Smrg
2235dfecf96Smrg/* neg */
2245dfecf96Smrgstatic void neg_real(n_real*);
2255dfecf96Smrgstatic void neg_number(n_number*);
2265dfecf96Smrgstatic void rneg_fi(n_real*);
2275dfecf96Smrgstatic INLINE void rneg_bi(n_real*);
2285dfecf96Smrgstatic INLINE void rneg_ff(n_real*);
2295dfecf96Smrgstatic INLINE void rneg_fr(n_real*);
2305dfecf96Smrgstatic INLINE void rneg_br(n_real*);
2315dfecf96Smrg
2325dfecf96Smrg/* sqrt */
2335dfecf96Smrgstatic void sqrt_real(n_real*);
2345dfecf96Smrgstatic void sqrt_number(n_number*);
2355dfecf96Smrgstatic void rsqrt_xi(n_real*);
2365dfecf96Smrgstatic void rsqrt_xr(n_real*);
2375dfecf96Smrgstatic void rsqrt_ff(n_real*);
2385dfecf96Smrgstatic void nsqrt_cx(n_number*);
2395dfecf96Smrgstatic void nsqrt_xi(n_number*);
2405dfecf96Smrgstatic void nsqrt_ff(n_number*);
2415dfecf96Smrgstatic void nsqrt_xr(n_number*);
2425dfecf96Smrg
2435dfecf96Smrg/* mod */
2445dfecf96Smrgstatic void mod_real_real(n_real*, n_real*);
2455dfecf96Smrgstatic void mod_real_object(n_real*, LispObj*);
2465dfecf96Smrgstatic void rmod_fi_fi(n_real*, long);
2475dfecf96Smrgstatic void rmod_fi_bi(n_real*, mpi*);
2485dfecf96Smrgstatic void rmod_bi_fi(n_real*, long);
2495dfecf96Smrgstatic void rmod_bi_bi(n_real*, mpi*);
2505dfecf96Smrg
2515dfecf96Smrg/* rem */
2525dfecf96Smrgstatic void rem_real_object(n_real*, LispObj*);
2535dfecf96Smrgstatic void rrem_fi_fi(n_real*, long);
2545dfecf96Smrgstatic void rrem_fi_bi(n_real*, mpi*);
2555dfecf96Smrgstatic void rrem_bi_fi(n_real*, long);
2565dfecf96Smrgstatic void rrem_bi_bi(n_real*, mpi*);
2575dfecf96Smrg
2585dfecf96Smrg/* gcd */
2595dfecf96Smrgstatic void gcd_real_object(n_real*, LispObj*);
2605dfecf96Smrg
2615dfecf96Smrg/* and */
2625dfecf96Smrgstatic void and_real_object(n_real*, LispObj*);
2635dfecf96Smrg
2645dfecf96Smrg/* eqv */
2655dfecf96Smrgstatic void eqv_real_object(n_real*, LispObj*);
2665dfecf96Smrg
2675dfecf96Smrg/* ior */
2685dfecf96Smrgstatic void ior_real_object(n_real*, LispObj*);
2695dfecf96Smrg
2705dfecf96Smrg/* not */
2715dfecf96Smrgstatic void not_real(n_real*);
2725dfecf96Smrg
2735dfecf96Smrg/* xor */
2745dfecf96Smrgstatic void xor_real_object(n_real*, LispObj*);
2755dfecf96Smrg
2765dfecf96Smrg/* divide */
2775dfecf96Smrgstatic void divide_number_object(n_number*, LispObj*, int, int);
2785dfecf96Smrgstatic void ndivide_xi_xi(n_number*, LispObj*, int, int);
2795dfecf96Smrgstatic void ndivide_flonum(n_number*, double, double, int, int);
2805dfecf96Smrgstatic void ndivide_xi_xr(n_number*, LispObj*, int, int);
2815dfecf96Smrgstatic void ndivide_xr_xi(n_number*, LispObj*, int, int);
2825dfecf96Smrgstatic void ndivide_xr_xr(n_number*, LispObj*, int, int);
2835dfecf96Smrg
2845dfecf96Smrg/* real complex */
2855dfecf96Smrgstatic void nadd_re_cx(n_number*, LispObj*);
2865dfecf96Smrgstatic void nsub_re_cx(n_number*, LispObj*);
2875dfecf96Smrgstatic void nmul_re_cx(n_number*, LispObj*);
2885dfecf96Smrgstatic void ndiv_re_cx(n_number*, LispObj*);
2895dfecf96Smrg
2905dfecf96Smrg/* complex real */
2915dfecf96Smrgstatic void nadd_cx_re(n_number*, LispObj*);
2925dfecf96Smrgstatic void nsub_cx_re(n_number*, LispObj*);
2935dfecf96Smrgstatic void nmul_cx_re(n_number*, LispObj*);
2945dfecf96Smrgstatic void ndiv_cx_re(n_number*, LispObj*);
2955dfecf96Smrg
2965dfecf96Smrg/* complex complex */
2975dfecf96Smrgstatic void nadd_cx_cx(n_number*, LispObj*);
2985dfecf96Smrgstatic void nsub_cx_cx(n_number*, LispObj*);
2995dfecf96Smrgstatic void nmul_cx_cx(n_number*, LispObj*);
3005dfecf96Smrgstatic void ndiv_cx_cx(n_number*, LispObj*);
3015dfecf96Smrgstatic int cmp_cx_cx(LispObj*, LispObj*);
3025dfecf96Smrg
3035dfecf96Smrg/* flonum flonum */
3045dfecf96Smrgstatic void radd_flonum(n_real*, double, double);
3055dfecf96Smrgstatic void rsub_flonum(n_real*, double, double);
3065dfecf96Smrgstatic void rmul_flonum(n_real*, double, double);
3075dfecf96Smrgstatic void rdiv_flonum(n_real*, double, double);
3085dfecf96Smrgstatic int cmp_flonum(double, double);
3095dfecf96Smrg
3105dfecf96Smrg/* fixnum fixnum */
3115dfecf96Smrgstatic void rop_fi_fi_bi(n_real*, long, int);
3125dfecf96Smrgstatic INLINE void radd_fi_fi(n_real*, long);
3135dfecf96Smrgstatic INLINE void rsub_fi_fi(n_real*, long);
3145dfecf96Smrgstatic INLINE void rmul_fi_fi(n_real*, long);
3155dfecf96Smrgstatic INLINE void rdiv_fi_fi(n_real*, long);
3165dfecf96Smrgstatic INLINE int cmp_fi_fi(long, long);
3175dfecf96Smrgstatic void ndivide_fi_fi(n_number*, long, int, int);
3185dfecf96Smrg
3195dfecf96Smrg/* fixnum bignum */
3205dfecf96Smrgstatic void rop_fi_bi_xi(n_real*, mpi*, int);
3215dfecf96Smrgstatic INLINE void radd_fi_bi(n_real*, mpi*);
3225dfecf96Smrgstatic INLINE void rsub_fi_bi(n_real*, mpi*);
3235dfecf96Smrgstatic INLINE void rmul_fi_bi(n_real*, mpi*);
3245dfecf96Smrgstatic void rdiv_fi_bi(n_real*, mpi*);
3255dfecf96Smrgstatic INLINE int cmp_fi_bi(long, mpi*);
3265dfecf96Smrg
3275dfecf96Smrg/* fixnum fixratio */
3285dfecf96Smrgstatic void rop_fi_fr_as_xr(n_real*, long, long, int);
3295dfecf96Smrgstatic void rop_fi_fr_md_xr(n_real*, long, long, int);
3305dfecf96Smrgstatic INLINE void radd_fi_fr(n_real*, long, long);
3315dfecf96Smrgstatic INLINE void rsub_fi_fr(n_real*, long, long);
3325dfecf96Smrgstatic INLINE void rmul_fi_fr(n_real*, long, long);
3335dfecf96Smrgstatic INLINE void rdiv_fi_fr(n_real*, long, long);
3345dfecf96Smrgstatic INLINE int cmp_fi_fr(long, long, long);
3355dfecf96Smrg
3365dfecf96Smrg/* fixnum bigratio */
3375dfecf96Smrgstatic void rop_fi_br_as_xr(n_real*, mpr*, int);
3385dfecf96Smrgstatic void rop_fi_br_md_xr(n_real*, mpr*, int);
3395dfecf96Smrgstatic INLINE void radd_fi_br(n_real*, mpr*);
3405dfecf96Smrgstatic INLINE void rsub_fi_br(n_real*, mpr*);
3415dfecf96Smrgstatic INLINE void rmul_fi_br(n_real*, mpr*);
3425dfecf96Smrgstatic INLINE void rdiv_fi_br(n_real*, mpr*);
3435dfecf96Smrgstatic INLINE int cmp_fi_br(long, mpr*);
3445dfecf96Smrg
3455dfecf96Smrg/* bignum fixnum */
3465dfecf96Smrgstatic INLINE void radd_bi_fi(n_real*, long);
3475dfecf96Smrgstatic INLINE void rsub_bi_fi(n_real*, long);
3485dfecf96Smrgstatic INLINE void rmul_bi_fi(n_real*, long);
3495dfecf96Smrgstatic void rdiv_bi_fi(n_real*, long);
3505dfecf96Smrgstatic INLINE int cmp_bi_fi(mpi*, long);
3515dfecf96Smrg
3525dfecf96Smrg/* bignum bignum */
3535dfecf96Smrgstatic INLINE void radd_bi_bi(n_real*, mpi*);
3545dfecf96Smrgstatic INLINE void rsub_bi_bi(n_real*, mpi*);
3555dfecf96Smrgstatic INLINE void rmul_bi_bi(n_real*, mpi*);
3565dfecf96Smrgstatic void rdiv_bi_bi(n_real*, mpi*);
3575dfecf96Smrgstatic INLINE int cmp_bi_bi(mpi*, mpi*);
3585dfecf96Smrg
3595dfecf96Smrg/* bignum fixratio */
3605dfecf96Smrgstatic void rop_bi_fr_as_xr(n_real*, long, long, int);
3615dfecf96Smrgstatic void rop_bi_fr_md_xr(n_real*, long, long, int);
3625dfecf96Smrgstatic INLINE void radd_bi_fr(n_real*, long, long);
3635dfecf96Smrgstatic INLINE void rsub_bi_fr(n_real*, long, long);
3645dfecf96Smrgstatic INLINE void rmul_bi_fr(n_real*, long, long);
3655dfecf96Smrgstatic INLINE void rdiv_bi_fr(n_real*, long, long);
3665dfecf96Smrgstatic int cmp_bi_fr(mpi*, long, long);
3675dfecf96Smrg
3685dfecf96Smrg/* bignum bigratio */
3695dfecf96Smrgstatic void rop_bi_br_as_xr(n_real*, mpr*, int);
3705dfecf96Smrgstatic void rop_bi_br_md_xr(n_real*, mpr*, int);
3715dfecf96Smrgstatic INLINE void radd_bi_br(n_real*, mpr*);
3725dfecf96Smrgstatic INLINE void rsub_bi_br(n_real*, mpr*);
3735dfecf96Smrgstatic INLINE void rmul_bi_br(n_real*, mpr*);
3745dfecf96Smrgstatic INLINE void rdiv_bi_br(n_real*, mpr*);
3755dfecf96Smrgstatic int cmp_bi_br(mpi*, mpr*);
3765dfecf96Smrg
3775dfecf96Smrg/* fixratio fixnum */
3785dfecf96Smrgstatic void rop_fr_fi_as_xr(n_real*, long, int);
3795dfecf96Smrgstatic void rop_fr_fi_md_xr(n_real*, long, int);
3805dfecf96Smrgstatic INLINE void radd_fr_fi(n_real*, long);
3815dfecf96Smrgstatic INLINE void rsub_fr_fi(n_real*, long);
3825dfecf96Smrgstatic INLINE void rmul_fr_fi(n_real*, long);
3835dfecf96Smrgstatic INLINE void rdiv_fr_fi(n_real*, long);
3845dfecf96Smrgstatic INLINE int cmp_fr_fi(long, long, long);
3855dfecf96Smrg
3865dfecf96Smrg/* fixratio bignum */
3875dfecf96Smrgstatic void rop_fr_bi_as_xr(n_real*, mpi*, int);
3885dfecf96Smrgstatic void rop_fr_bi_md_xr(n_real*, mpi*, int);
3895dfecf96Smrgstatic INLINE void radd_fr_bi(n_real*, mpi*);
3905dfecf96Smrgstatic INLINE void rsub_fr_bi(n_real*, mpi*);
3915dfecf96Smrgstatic INLINE void rmul_fr_bi(n_real*, mpi*);
3925dfecf96Smrgstatic INLINE void rdiv_fr_bi(n_real*, mpi*);
3935dfecf96Smrgstatic int cmp_fr_bi(long, long, mpi*);
3945dfecf96Smrg
3955dfecf96Smrg/* fixratio fixratio */
3965dfecf96Smrgstatic void rop_fr_fr_as_xr(n_real*, long, long, int);
3975dfecf96Smrgstatic void rop_fr_fr_md_xr(n_real*, long, long, int);
3985dfecf96Smrgstatic INLINE void radd_fr_fr(n_real*, long, long);
3995dfecf96Smrgstatic INLINE void rsub_fr_fr(n_real*, long, long);
4005dfecf96Smrgstatic INLINE void rmul_fr_fr(n_real*, long, long);
4015dfecf96Smrgstatic INLINE void rdiv_fr_fr(n_real*, long, long);
4025dfecf96Smrgstatic INLINE int cmp_fr_fr(long, long, long, long);
4035dfecf96Smrg
4045dfecf96Smrg/* fixratio bigratio */
4055dfecf96Smrgstatic void rop_fr_br_asmd_xr(n_real*, mpr*, int);
4065dfecf96Smrgstatic INLINE void radd_fr_br(n_real*, mpr*);
4075dfecf96Smrgstatic INLINE void rsub_fr_br(n_real*, mpr*);
4085dfecf96Smrgstatic INLINE void rmul_fr_br(n_real*, mpr*);
4095dfecf96Smrgstatic INLINE void rdiv_fr_br(n_real*, mpr*);
4105dfecf96Smrgstatic int cmp_fr_br(long, long, mpr*);
4115dfecf96Smrg
4125dfecf96Smrg/* bigratio fixnum */
4135dfecf96Smrgstatic void rop_br_fi_asmd_xr(n_real*, long, int);
4145dfecf96Smrgstatic INLINE void radd_br_fi(n_real*, long);
4155dfecf96Smrgstatic INLINE void rsub_br_fi(n_real*, long);
4165dfecf96Smrgstatic INLINE void rmul_br_fi(n_real*, long);
4175dfecf96Smrgstatic INLINE void rdiv_br_fi(n_real*, long);
4185dfecf96Smrgstatic int cmp_br_fi(mpr*, long);
4195dfecf96Smrg
4205dfecf96Smrg/* bigratio bignum */
4215dfecf96Smrgstatic void rop_br_bi_as_xr(n_real*, mpi*, int);
4225dfecf96Smrgstatic INLINE void radd_br_bi(n_real*, mpi*);
4235dfecf96Smrgstatic INLINE void rsub_br_bi(n_real*, mpi*);
4245dfecf96Smrgstatic INLINE void rmul_br_bi(n_real*, mpi*);
4255dfecf96Smrgstatic INLINE void rdiv_br_bi(n_real*, mpi*);
4265dfecf96Smrgstatic int cmp_br_bi(mpr*, mpi*);
4275dfecf96Smrg
4285dfecf96Smrg/* bigratio fixratio */
4295dfecf96Smrgstatic void rop_br_fr_asmd_xr(n_real*, long, long, int);
4305dfecf96Smrgstatic INLINE void radd_br_fr(n_real*, long, long);
4315dfecf96Smrgstatic INLINE void rsub_br_fr(n_real*, long, long);
4325dfecf96Smrgstatic INLINE void rmul_br_fr(n_real*, long, long);
4335dfecf96Smrgstatic INLINE void rdiv_br_fr(n_real*, long, long);
4345dfecf96Smrgstatic int cmp_br_fr(mpr*, long, long);
4355dfecf96Smrg
4365dfecf96Smrg/* bigratio bigratio */
4375dfecf96Smrgstatic INLINE void radd_br_br(n_real*, mpr*);
4385dfecf96Smrgstatic INLINE void rsub_br_br(n_real*, mpr*);
4395dfecf96Smrgstatic INLINE void rmul_br_br(n_real*, mpr*);
4405dfecf96Smrgstatic INLINE void rdiv_br_br(n_real*, mpr*);
4415dfecf96Smrgstatic INLINE int cmp_br_br(mpr*, mpr*);
4425dfecf96Smrg
4435dfecf96Smrg/*
4445dfecf96Smrg * Initialization
4455dfecf96Smrg */
4465dfecf96Smrgstatic n_real zero, one, two;
4475dfecf96Smrg
4485dfecf96Smrgstatic char *fatal_error_strings[] = {
4495dfecf96Smrg#define DIVIDE_BY_ZERO			0
4505dfecf96Smrg    "divide by zero",
4515dfecf96Smrg#define FLOATING_POINT_OVERFLOW		1
4525dfecf96Smrg    "floating point overflow",
4535dfecf96Smrg#define FLOATING_POINT_EXCEPTION	2
4545dfecf96Smrg    "floating point exception"
4555dfecf96Smrg};
4565dfecf96Smrg
4575dfecf96Smrgstatic char *fatal_object_error_strings[] = {
4585dfecf96Smrg#define NOT_A_NUMBER			0
4595dfecf96Smrg    "is not a number",
4605dfecf96Smrg#define NOT_A_REAL_NUMBER		1
4615dfecf96Smrg    "is not a real number",
4625dfecf96Smrg#define NOT_AN_INTEGER			2
4635dfecf96Smrg    "is not an integer"
4645dfecf96Smrg};
4655dfecf96Smrg
4665dfecf96Smrg/*
4675dfecf96Smrg * Implementation
4685dfecf96Smrg */
4695dfecf96Smrgstatic void
4705dfecf96Smrgfatal_error(int num)
4715dfecf96Smrg{
4725dfecf96Smrg    LispDestroy(fatal_error_strings[num]);
4735dfecf96Smrg}
4745dfecf96Smrg
4755dfecf96Smrgstatic void
4765dfecf96Smrgfatal_object_error(LispObj *obj, int num)
4775dfecf96Smrg{
4785dfecf96Smrg    LispDestroy("%s %s", STROBJ(obj), fatal_object_error_strings[num]);
4795dfecf96Smrg}
4805dfecf96Smrg
4815dfecf96Smrgstatic void
4825dfecf96Smrgfatal_builtin_object_error(LispBuiltin *builtin, LispObj *obj, int num)
4835dfecf96Smrg{
4845dfecf96Smrg    LispDestroy("%s: %s %s", STRFUN(builtin), STROBJ(obj),
4855dfecf96Smrg		fatal_object_error_strings[num]);
4865dfecf96Smrg}
4875dfecf96Smrg
4885dfecf96Smrgstatic void
4895dfecf96Smrgnumber_init(void)
4905dfecf96Smrg{
4915dfecf96Smrg    zero.type = one.type = two.type = N_FIXNUM;
4925dfecf96Smrg    zero.data.fixnum = 0;
4935dfecf96Smrg    one.data.fixnum = 1;
4945dfecf96Smrg    two.data.fixnum = 2;
4955dfecf96Smrg}
4965dfecf96Smrg
4975dfecf96Smrgstatic double
4985dfecf96Smrgbi_getd(mpi *bignum)
4995dfecf96Smrg{
5005dfecf96Smrg    double value = mpi_getd(bignum);
5015dfecf96Smrg
5025dfecf96Smrg    if (!finite(value))
5035dfecf96Smrg	fatal_error(FLOATING_POINT_EXCEPTION);
5045dfecf96Smrg
5055dfecf96Smrg    return (value);
5065dfecf96Smrg}
5075dfecf96Smrg
5085dfecf96Smrgstatic double
5095dfecf96Smrgbr_getd(mpr *bigratio)
5105dfecf96Smrg{
5115dfecf96Smrg    double value = mpr_getd(bigratio);
5125dfecf96Smrg
5135dfecf96Smrg    if (!finite(value))
5145dfecf96Smrg	fatal_error(FLOATING_POINT_EXCEPTION);
5155dfecf96Smrg
5165dfecf96Smrg    return (value);
5175dfecf96Smrg}
5185dfecf96Smrg
5195dfecf96Smrgstatic LispObj *
5205dfecf96Smrgnumber_pi(void)
5215dfecf96Smrg{
5225dfecf96Smrg    LispObj *result;
5235dfecf96Smrg#ifndef M_PI
5245dfecf96Smrg#define M_PI 3.14159265358979323846
5255dfecf96Smrg#endif
5265dfecf96Smrg    result = DFLOAT(M_PI);
5275dfecf96Smrg
5285dfecf96Smrg    return (result);
5295dfecf96Smrg}
5305dfecf96Smrg
5315dfecf96Smrgstatic void
5325dfecf96Smrgset_real_real(n_real *real, n_real *val)
5335dfecf96Smrg{
5345dfecf96Smrg    switch (RTYPE(real) = RTYPE(val)) {
5355dfecf96Smrg	case N_FIXNUM:
5365dfecf96Smrg	    RFI(real) = RFI(val);
5375dfecf96Smrg	    break;
5385dfecf96Smrg	case N_BIGNUM:
5395dfecf96Smrg	    RBI(real) = XALLOC(mpi);
5405dfecf96Smrg	    mpi_init(RBI(real));
5415dfecf96Smrg	    mpi_set(RBI(real), RBI(val));
5425dfecf96Smrg	    break;
5435dfecf96Smrg	case N_FLONUM:
5445dfecf96Smrg	    RFF(real) = RFF(val);
5455dfecf96Smrg	    break;
5465dfecf96Smrg	case N_FIXRATIO:
5475dfecf96Smrg	    RFRN(real) = RFRN(val);
5485dfecf96Smrg	    RFRD(real) = RFRD(val);
5495dfecf96Smrg	    break;
5505dfecf96Smrg	case N_BIGRATIO:
5515dfecf96Smrg	    RBR(real) = XALLOC(mpr);
5525dfecf96Smrg	    mpr_init(RBR(real));
5535dfecf96Smrg	    mpr_set(RBR(real), RBR(val));
5545dfecf96Smrg	    break;
5555dfecf96Smrg    }
5565dfecf96Smrg}
5575dfecf96Smrg
5585dfecf96Smrgstatic void
5595dfecf96Smrgset_real_object(n_real *real, LispObj *obj)
5605dfecf96Smrg{
5615dfecf96Smrg    switch (OBJECT_TYPE(obj)) {
5625dfecf96Smrg	case LispFixnum_t:
5635dfecf96Smrg	    RTYPE(real) = N_FIXNUM;
5645dfecf96Smrg	    RFI(real) = OFI(obj);
5655dfecf96Smrg	    break;
5665dfecf96Smrg	case LispInteger_t:
5675dfecf96Smrg	    RTYPE(real) = N_FIXNUM;
5685dfecf96Smrg	    RFI(real) = OII(obj);
5695dfecf96Smrg	    break;
5705dfecf96Smrg	case LispBignum_t:
5715dfecf96Smrg	    RTYPE(real) = N_BIGNUM;
5725dfecf96Smrg	    RBI(real) = XALLOC(mpi);
5735dfecf96Smrg	    mpi_init(RBI(real));
5745dfecf96Smrg	    mpi_set(RBI(real), OBI(obj));
5755dfecf96Smrg	    break;
5765dfecf96Smrg	case LispDFloat_t:
5775dfecf96Smrg	    RTYPE(real) = N_FLONUM;
5785dfecf96Smrg	    RFF(real) = ODF(obj);
5795dfecf96Smrg	    break;
5805dfecf96Smrg	case LispRatio_t:
5815dfecf96Smrg	    RTYPE(real) = N_FIXRATIO;
5825dfecf96Smrg	    RFRN(real) = OFRN(obj);
5835dfecf96Smrg	    RFRD(real) = OFRD(obj);
5845dfecf96Smrg	    break;
5855dfecf96Smrg	case LispBigratio_t:
5865dfecf96Smrg	    RTYPE(real) = N_BIGRATIO;
5875dfecf96Smrg	    RBR(real) = XALLOC(mpr);
5885dfecf96Smrg	    mpr_init(RBR(real));
5895dfecf96Smrg	    mpr_set(RBR(real), OBR(obj));
5905dfecf96Smrg	    break;
5915dfecf96Smrg	default:
5925dfecf96Smrg	    fatal_object_error(obj, NOT_A_REAL_NUMBER);
5935dfecf96Smrg	    break;
5945dfecf96Smrg    }
5955dfecf96Smrg}
5965dfecf96Smrg
5975dfecf96Smrgstatic void
5985dfecf96Smrgset_number_object(n_number *num, LispObj *obj)
5995dfecf96Smrg{
6005dfecf96Smrg    switch (OBJECT_TYPE(obj)) {
6015dfecf96Smrg	case LispFixnum_t:
6025dfecf96Smrg	    num->complex = 0;
6035dfecf96Smrg	    NRTYPE(num) = N_FIXNUM;
6045dfecf96Smrg	    NRFI(num) = OFI(obj);
6055dfecf96Smrg	    break;
6065dfecf96Smrg	case LispInteger_t:
6075dfecf96Smrg	    num->complex = 0;
6085dfecf96Smrg	    NRTYPE(num) = N_FIXNUM;
6095dfecf96Smrg	    NRFI(num) = OII(obj);
6105dfecf96Smrg	    break;
6115dfecf96Smrg	case LispBignum_t:
6125dfecf96Smrg	    num->complex = 0;
6135dfecf96Smrg	    NRTYPE(num) = N_BIGNUM;
6145dfecf96Smrg	    NRBI(num) = XALLOC(mpi);
6155dfecf96Smrg	    mpi_init(NRBI(num));
6165dfecf96Smrg	    mpi_set(NRBI(num), OBI(obj));
6175dfecf96Smrg	    break;
6185dfecf96Smrg	case LispDFloat_t:
6195dfecf96Smrg	    num->complex = 0;
6205dfecf96Smrg	    NRTYPE(num) = N_FLONUM;
6215dfecf96Smrg	    NRFF(num) = ODF(obj);
6225dfecf96Smrg	    break;
6235dfecf96Smrg	case LispRatio_t:
6245dfecf96Smrg	    num->complex = 0;
6255dfecf96Smrg	    NRTYPE(num) = N_FIXRATIO;
6265dfecf96Smrg	    NRFRN(num) = OFRN(obj);
6275dfecf96Smrg	    NRFRD(num) = OFRD(obj);
6285dfecf96Smrg	    break;
6295dfecf96Smrg	case LispBigratio_t:
6305dfecf96Smrg	    num->complex = 0;
6315dfecf96Smrg	    NRTYPE(num) = N_BIGRATIO;
6325dfecf96Smrg	    NRBR(num) = XALLOC(mpr);
6335dfecf96Smrg	    mpr_init(NRBR(num));
6345dfecf96Smrg	    mpr_set(NRBR(num), OBR(obj));
6355dfecf96Smrg	    break;
6365dfecf96Smrg	case LispComplex_t:
6375dfecf96Smrg	    num->complex = 1;
6385dfecf96Smrg	    set_real_object(NREAL(num), OCXR(obj));
6395dfecf96Smrg	    set_real_object(NIMAG(num), OCXI(obj));
6405dfecf96Smrg	    break;
6415dfecf96Smrg	default:
6425dfecf96Smrg	    fatal_object_error(obj, NOT_A_NUMBER);
6435dfecf96Smrg	    break;
6445dfecf96Smrg    }
6455dfecf96Smrg}
6465dfecf96Smrg
6475dfecf96Smrgstatic void
6485dfecf96Smrgclear_real(n_real *real)
6495dfecf96Smrg{
6505dfecf96Smrg    if (RTYPE(real) == N_BIGNUM) {
6515dfecf96Smrg	mpi_clear(RBI(real));
6525dfecf96Smrg	XFREE(RBI(real));
6535dfecf96Smrg    }
6545dfecf96Smrg    else if (RTYPE(real) == N_BIGRATIO) {
6555dfecf96Smrg	mpr_clear(RBR(real));
6565dfecf96Smrg	XFREE(RBR(real));
6575dfecf96Smrg    }
6585dfecf96Smrg}
6595dfecf96Smrg
6605dfecf96Smrgstatic void
6615dfecf96Smrgclear_number(n_number *num)
6625dfecf96Smrg{
6635dfecf96Smrg    clear_real(NREAL(num));
6645dfecf96Smrg    if (num->complex)
6655dfecf96Smrg	clear_real(NIMAG(num));
6665dfecf96Smrg}
6675dfecf96Smrg
6685dfecf96Smrgstatic LispObj *
6695dfecf96Smrgmake_real_object(n_real *real)
6705dfecf96Smrg{
6715dfecf96Smrg    LispObj *obj;
6725dfecf96Smrg
6735dfecf96Smrg    switch (RTYPE(real)) {
6745dfecf96Smrg	case N_FIXNUM:
6755dfecf96Smrg	    if (RFI(real) > MOST_POSITIVE_FIXNUM ||
6765dfecf96Smrg		RFI(real) < MOST_NEGATIVE_FIXNUM) {
6775dfecf96Smrg		obj = LispNew(NIL, NIL);
6785dfecf96Smrg		obj->type = LispInteger_t;
6795dfecf96Smrg		OII(obj) = RFI(real);
6805dfecf96Smrg	    }
6815dfecf96Smrg	    else
6825dfecf96Smrg		obj = FIXNUM(RFI(real));
6835dfecf96Smrg	    break;
6845dfecf96Smrg	case N_BIGNUM:
6855dfecf96Smrg	    obj = BIGNUM(RBI(real));
6865dfecf96Smrg	    break;
6875dfecf96Smrg	case N_FLONUM:
6885dfecf96Smrg	    obj = DFLOAT(RFF(real));
6895dfecf96Smrg	    break;
6905dfecf96Smrg	case N_FIXRATIO:
6915dfecf96Smrg	    obj = LispNew(NIL, NIL);
6925dfecf96Smrg	    obj->type = LispRatio_t;
6935dfecf96Smrg	    OFRN(obj) = RFRN(real);
6945dfecf96Smrg	    OFRD(obj) = RFRD(real);
6955dfecf96Smrg	    break;
6965dfecf96Smrg	case N_BIGRATIO:
6975dfecf96Smrg	    obj = BIGRATIO(RBR(real));
6985dfecf96Smrg	    break;
6995dfecf96Smrg	default:
7005dfecf96Smrg	    obj = NIL;
7015dfecf96Smrg	    break;
7025dfecf96Smrg    }
7035dfecf96Smrg
7045dfecf96Smrg    return (obj);
7055dfecf96Smrg}
7065dfecf96Smrg
7075dfecf96Smrgstatic LispObj *
7085dfecf96Smrgmake_number_object(n_number *num)
7095dfecf96Smrg{
7105dfecf96Smrg    LispObj *obj;
7115dfecf96Smrg
7125dfecf96Smrg    if (num->complex) {
7135dfecf96Smrg	GC_ENTER();
7145dfecf96Smrg
7155dfecf96Smrg	obj = LispNew(NIL, NIL);
7165dfecf96Smrg	GC_PROTECT(obj);
7175dfecf96Smrg	OCXI(obj) = NIL;
7185dfecf96Smrg	obj->type = LispComplex_t;
7195dfecf96Smrg	OCXR(obj) = make_real_object(NREAL(num));
7205dfecf96Smrg	OCXI(obj) = make_real_object(NIMAG(num));
7215dfecf96Smrg	GC_LEAVE();
7225dfecf96Smrg    }
7235dfecf96Smrg    else {
7245dfecf96Smrg	switch (NRTYPE(num)) {
7255dfecf96Smrg	    case N_FIXNUM:
7265dfecf96Smrg		if (NRFI(num) > MOST_POSITIVE_FIXNUM ||
7275dfecf96Smrg		    NRFI(num) < MOST_NEGATIVE_FIXNUM) {
7285dfecf96Smrg		    obj = LispNew(NIL, NIL);
7295dfecf96Smrg		    obj->type = LispInteger_t;
7305dfecf96Smrg		    OII(obj) = NRFI(num);
7315dfecf96Smrg		}
7325dfecf96Smrg		else
7335dfecf96Smrg		    obj = FIXNUM(NRFI(num));
7345dfecf96Smrg		break;
7355dfecf96Smrg	    case N_BIGNUM:
7365dfecf96Smrg		obj = BIGNUM(NRBI(num));
7375dfecf96Smrg		break;
7385dfecf96Smrg	    case N_FLONUM:
7395dfecf96Smrg		obj = DFLOAT(NRFF(num));
7405dfecf96Smrg		break;
7415dfecf96Smrg	    case N_FIXRATIO:
7425dfecf96Smrg		obj = LispNew(NIL, NIL);
7435dfecf96Smrg		obj->type = LispRatio_t;
7445dfecf96Smrg		OFRN(obj) = NRFRN(num);
7455dfecf96Smrg		OFRD(obj) = NRFRD(num);
7465dfecf96Smrg		break;
7475dfecf96Smrg	    case N_BIGRATIO:
7485dfecf96Smrg		obj = BIGRATIO(NRBR(num));
7495dfecf96Smrg		break;
7505dfecf96Smrg	    default:
7515dfecf96Smrg		obj = NIL;
7525dfecf96Smrg		break;
7535dfecf96Smrg	}
7545dfecf96Smrg    }
7555dfecf96Smrg
7565dfecf96Smrg    return (obj);
7575dfecf96Smrg}
7585dfecf96Smrg
7595dfecf96Smrg#define DEFOP_REAL_REAL(OP)						\
7605dfecf96SmrgOP##_real_real(n_real *real, n_real *val)				\
7615dfecf96Smrg{									\
7625dfecf96Smrg    switch (RTYPE(real)) {						\
7635dfecf96Smrg	case N_FIXNUM:							\
7645dfecf96Smrg	    switch (RTYPE(val)) {					\
7655dfecf96Smrg		case N_FIXNUM:						\
7665dfecf96Smrg		    r##OP##_fi_fi(real, RFI(val));			\
7675dfecf96Smrg		    break;						\
7685dfecf96Smrg		case N_BIGNUM:						\
7695dfecf96Smrg		    r##OP##_fi_bi(real, RBI(val));			\
7705dfecf96Smrg		    break;						\
7715dfecf96Smrg		case N_FLONUM:						\
7725dfecf96Smrg		    r##OP##_flonum(real, (double)RFI(real), RFF(val));	\
7735dfecf96Smrg		    break;						\
7745dfecf96Smrg		case N_FIXRATIO:					\
7755dfecf96Smrg		    r##OP##_fi_fr(real, RFRN(val), RFRD(val));		\
7765dfecf96Smrg		    break;						\
7775dfecf96Smrg		case N_BIGRATIO:					\
7785dfecf96Smrg		    r##OP##_fi_br(real, RBR(val));			\
7795dfecf96Smrg		    break;						\
7805dfecf96Smrg	    }								\
7815dfecf96Smrg	    break;							\
7825dfecf96Smrg	case N_BIGNUM:							\
7835dfecf96Smrg	    switch (RTYPE(val)) {					\
7845dfecf96Smrg		case N_FIXNUM:						\
7855dfecf96Smrg		    r##OP##_bi_fi(real, RFI(val));			\
7865dfecf96Smrg		    break;						\
7875dfecf96Smrg		case N_BIGNUM:						\
7885dfecf96Smrg		    r##OP##_bi_bi(real, RBI(val));			\
7895dfecf96Smrg		    break;						\
7905dfecf96Smrg		case N_FLONUM:						\
7915dfecf96Smrg		    r##OP##_flonum(real, bi_getd(RBI(real)), RFF(val));	\
7925dfecf96Smrg		    break;						\
7935dfecf96Smrg		case N_FIXRATIO:					\
7945dfecf96Smrg		    r##OP##_bi_fr(real, RFRN(val), RFRD(val));		\
7955dfecf96Smrg		    break;						\
7965dfecf96Smrg		case N_BIGRATIO:					\
7975dfecf96Smrg		    r##OP##_bi_br(real, RBR(val));			\
7985dfecf96Smrg		    break;						\
7995dfecf96Smrg	    }								\
8005dfecf96Smrg	    break;							\
8015dfecf96Smrg	case N_FLONUM:							\
8025dfecf96Smrg	    switch (RTYPE(val)) {					\
8035dfecf96Smrg		case N_FIXNUM:						\
8045dfecf96Smrg		    r##OP##_flonum(real, RFF(real), (double)RFI(val));	\
8055dfecf96Smrg		    break;						\
8065dfecf96Smrg		case N_BIGNUM:						\
8075dfecf96Smrg		    r##OP##_flonum(real, RFF(real), bi_getd(RBI(val)));	\
8085dfecf96Smrg		    break;						\
8095dfecf96Smrg		case N_FLONUM:						\
8105dfecf96Smrg		    r##OP##_flonum(real, RFF(real), RFF(val));		\
8115dfecf96Smrg		    break;						\
8125dfecf96Smrg		case N_FIXRATIO:					\
8135dfecf96Smrg		    r##OP##_flonum(real, RFF(real),			\
8145dfecf96Smrg				 (double)RFRN(val) / (double)RFRD(val));\
8155dfecf96Smrg		    break;						\
8165dfecf96Smrg		case N_BIGRATIO:					\
8175dfecf96Smrg		    r##OP##_flonum(real, RFF(real), br_getd(RBR(val)));	\
8185dfecf96Smrg		    break;						\
8195dfecf96Smrg	    }								\
8205dfecf96Smrg	    break;							\
8215dfecf96Smrg	case N_FIXRATIO:						\
8225dfecf96Smrg	    switch (RTYPE(val)) {					\
8235dfecf96Smrg		case N_FIXNUM:						\
8245dfecf96Smrg		    r##OP##_fr_fi(real, RFI(val));			\
8255dfecf96Smrg		    break;						\
8265dfecf96Smrg		case N_BIGNUM:						\
8275dfecf96Smrg		    r##OP##_fr_bi(real, RBI(val));			\
8285dfecf96Smrg		    break;						\
8295dfecf96Smrg		case N_FLONUM:						\
8305dfecf96Smrg		    r##OP##_flonum(real,				\
8315dfecf96Smrg				(double)RFRN(real) / (double)RFRD(real),\
8325dfecf96Smrg				RFF(val));				\
8335dfecf96Smrg		    break;						\
8345dfecf96Smrg		case N_FIXRATIO:					\
8355dfecf96Smrg		    r##OP##_fr_fr(real, RFRN(val), RFRD(val));		\
8365dfecf96Smrg		    break;						\
8375dfecf96Smrg		case N_BIGRATIO:					\
8385dfecf96Smrg		    r##OP##_fr_br(real, RBR(val));			\
8395dfecf96Smrg		    break;						\
8405dfecf96Smrg	    }								\
8415dfecf96Smrg	    break;							\
8425dfecf96Smrg	case N_BIGRATIO:						\
8435dfecf96Smrg	    switch (RTYPE(val)) {					\
8445dfecf96Smrg		case N_FIXNUM:						\
8455dfecf96Smrg		    r##OP##_br_fi(real, RFI(val));			\
8465dfecf96Smrg		    break;						\
8475dfecf96Smrg		case N_BIGNUM:						\
8485dfecf96Smrg		    r##OP##_br_bi(real, RBI(val));			\
8495dfecf96Smrg		    break;						\
8505dfecf96Smrg		case N_FLONUM:						\
8515dfecf96Smrg		    r##OP##_flonum(real, br_getd(RBR(real)), RFF(val));	\
8525dfecf96Smrg		    break;						\
8535dfecf96Smrg		case N_FIXRATIO:					\
8545dfecf96Smrg		    r##OP##_br_fr(real, RFRN(val), RFRD(val));		\
8555dfecf96Smrg		    break;						\
8565dfecf96Smrg		case N_BIGRATIO:					\
8575dfecf96Smrg		    r##OP##_br_br(real, RBR(val));			\
8585dfecf96Smrg		    break;						\
8595dfecf96Smrg	    }								\
8605dfecf96Smrg	    break;							\
8615dfecf96Smrg    }									\
8625dfecf96Smrg}
8635dfecf96Smrg
8645dfecf96Smrgstatic void
8655dfecf96SmrgDEFOP_REAL_REAL(add)
8665dfecf96Smrg
8675dfecf96Smrgstatic void
8685dfecf96SmrgDEFOP_REAL_REAL(sub)
8695dfecf96Smrg
8705dfecf96Smrgstatic void
8715dfecf96SmrgDEFOP_REAL_REAL(div)
8725dfecf96Smrg
8735dfecf96Smrgstatic void
8745dfecf96SmrgDEFOP_REAL_REAL(mul)
8755dfecf96Smrg
8765dfecf96Smrg
8775dfecf96Smrg#define DEFOP_REAL_OBJECT(OP)						\
8785dfecf96SmrgOP##_real_object(n_real *real, LispObj *obj)				\
8795dfecf96Smrg{									\
8805dfecf96Smrg    switch (OBJECT_TYPE(obj)) {						\
8815dfecf96Smrg	case LispFixnum_t:						\
8825dfecf96Smrg	    switch (RTYPE(real)) {					\
8835dfecf96Smrg		case N_FIXNUM:						\
8845dfecf96Smrg		    r##OP##_fi_fi(real, OFI(obj));			\
8855dfecf96Smrg		    break;						\
8865dfecf96Smrg		case N_BIGNUM:						\
8875dfecf96Smrg		    r##OP##_bi_fi(real, OFI(obj));			\
8885dfecf96Smrg		    break;						\
8895dfecf96Smrg		case N_FLONUM:						\
8905dfecf96Smrg		    r##OP##_flonum(real, RFF(real), (double)OFI(obj));	\
8915dfecf96Smrg		    break;						\
8925dfecf96Smrg		case N_FIXRATIO:					\
8935dfecf96Smrg		    r##OP##_fr_fi(real, OFI(obj));			\
8945dfecf96Smrg		    break;						\
8955dfecf96Smrg		case N_BIGRATIO:					\
8965dfecf96Smrg		    r##OP##_br_fi(real, OFI(obj));			\
8975dfecf96Smrg		    break;						\
8985dfecf96Smrg	    }								\
8995dfecf96Smrg	    break;							\
9005dfecf96Smrg	case LispInteger_t:						\
9015dfecf96Smrg	    switch (RTYPE(real)) {					\
9025dfecf96Smrg		case N_FIXNUM:						\
9035dfecf96Smrg		    r##OP##_fi_fi(real, OII(obj));			\
9045dfecf96Smrg		    break;						\
9055dfecf96Smrg		case N_BIGNUM:						\
9065dfecf96Smrg		    r##OP##_bi_fi(real, OII(obj));			\
9075dfecf96Smrg		    break;						\
9085dfecf96Smrg		case N_FLONUM:						\
9095dfecf96Smrg		    r##OP##_flonum(real, RFF(real), (double)OII(obj));	\
9105dfecf96Smrg		    break;						\
9115dfecf96Smrg		case N_FIXRATIO:					\
9125dfecf96Smrg		    r##OP##_fr_fi(real, OII(obj));			\
9135dfecf96Smrg		    break;						\
9145dfecf96Smrg		case N_BIGRATIO:					\
9155dfecf96Smrg		    r##OP##_br_fi(real, OII(obj));			\
9165dfecf96Smrg		    break;						\
9175dfecf96Smrg	    }								\
9185dfecf96Smrg	    break;							\
9195dfecf96Smrg	case LispBignum_t:						\
9205dfecf96Smrg	    switch (RTYPE(real)) {					\
9215dfecf96Smrg		case N_FIXNUM:						\
9225dfecf96Smrg		    r##OP##_fi_bi(real, OBI(obj));			\
9235dfecf96Smrg		    break;						\
9245dfecf96Smrg		case N_BIGNUM:						\
9255dfecf96Smrg		    r##OP##_bi_bi(real, OBI(obj));			\
9265dfecf96Smrg		    break;						\
9275dfecf96Smrg		case N_FLONUM:						\
9285dfecf96Smrg		    r##OP##_flonum(real, RFF(real), bi_getd(OBI(obj)));	\
9295dfecf96Smrg		    break;						\
9305dfecf96Smrg		case N_FIXRATIO:					\
9315dfecf96Smrg		    r##OP##_fr_bi(real, OBI(obj));			\
9325dfecf96Smrg		    break;						\
9335dfecf96Smrg		case N_BIGRATIO:					\
9345dfecf96Smrg		    r##OP##_br_bi(real, OBI(obj));			\
9355dfecf96Smrg		    break;						\
9365dfecf96Smrg	    }								\
9375dfecf96Smrg	    break;							\
9385dfecf96Smrg	case LispDFloat_t:						\
9395dfecf96Smrg	    switch (RTYPE(real)) {					\
9405dfecf96Smrg		case N_FIXNUM:						\
9415dfecf96Smrg		    r##OP##_flonum(real, (double)RFI(real), ODF(obj));	\
9425dfecf96Smrg		    break;						\
9435dfecf96Smrg		case N_BIGNUM:						\
9445dfecf96Smrg		    r##OP##_flonum(real, bi_getd(RBI(real)), ODF(obj));	\
9455dfecf96Smrg		    break;						\
9465dfecf96Smrg		case N_FLONUM:						\
9475dfecf96Smrg		    r##OP##_flonum(real, RFF(real), ODF(obj));		\
9485dfecf96Smrg		    break;						\
9495dfecf96Smrg		case N_FIXRATIO:					\
9505dfecf96Smrg		    r##OP##_flonum(real,				\
9515dfecf96Smrg				(double)RFRN(real) / (double)RFRD(real),\
9525dfecf96Smrg				ODF(obj));				\
9535dfecf96Smrg		    break;						\
9545dfecf96Smrg		case N_BIGRATIO:					\
9555dfecf96Smrg		    r##OP##_flonum(real, br_getd(RBR(real)), ODF(obj));	\
9565dfecf96Smrg		    break;						\
9575dfecf96Smrg	    }								\
9585dfecf96Smrg	    break;							\
9595dfecf96Smrg	case LispRatio_t:						\
9605dfecf96Smrg	    switch (RTYPE(real)) {					\
9615dfecf96Smrg		case N_FIXNUM:						\
9625dfecf96Smrg		    r##OP##_fi_fr(real, OFRN(obj), OFRD(obj));		\
9635dfecf96Smrg		    break;						\
9645dfecf96Smrg		case N_BIGNUM:						\
9655dfecf96Smrg		    r##OP##_bi_fr(real, OFRN(obj), OFRD(obj));		\
9665dfecf96Smrg		    break;						\
9675dfecf96Smrg		case N_FLONUM:						\
9685dfecf96Smrg		    r##OP##_flonum(real, RFF(real),			\
9695dfecf96Smrg				(double)OFRN(obj) / (double)OFRD(obj));	\
9705dfecf96Smrg		    break;						\
9715dfecf96Smrg		case N_FIXRATIO:					\
9725dfecf96Smrg		    r##OP##_fr_fr(real, OFRN(obj), OFRD(obj));		\
9735dfecf96Smrg		    break;						\
9745dfecf96Smrg		case N_BIGRATIO:					\
9755dfecf96Smrg		    r##OP##_br_fr(real, OFRN(obj), OFRD(obj));		\
9765dfecf96Smrg		    break;						\
9775dfecf96Smrg	    }								\
9785dfecf96Smrg	    break;							\
9795dfecf96Smrg	case LispBigratio_t:						\
9805dfecf96Smrg	    switch (RTYPE(real)) {					\
9815dfecf96Smrg		case N_FIXNUM:						\
9825dfecf96Smrg		    r##OP##_fi_br(real, OBR(obj));			\
9835dfecf96Smrg		    break;						\
9845dfecf96Smrg		case N_BIGNUM:						\
9855dfecf96Smrg		    r##OP##_bi_br(real, OBR(obj));			\
9865dfecf96Smrg		    break;						\
9875dfecf96Smrg		case N_FLONUM:						\
9885dfecf96Smrg		    r##OP##_flonum(real, RFF(real), br_getd(OBR(obj)));	\
9895dfecf96Smrg		    break;						\
9905dfecf96Smrg		case N_FIXRATIO:					\
9915dfecf96Smrg		    r##OP##_fr_br(real, OBR(obj));			\
9925dfecf96Smrg		    break;						\
9935dfecf96Smrg		case N_BIGRATIO:					\
9945dfecf96Smrg		    r##OP##_br_br(real, OBR(obj));			\
9955dfecf96Smrg		    break;						\
9965dfecf96Smrg	    }								\
9975dfecf96Smrg	    break;							\
9985dfecf96Smrg	default:							\
9995dfecf96Smrg	    fatal_object_error(obj, NOT_A_REAL_NUMBER);			\
10005dfecf96Smrg	    break;							\
10015dfecf96Smrg    }									\
10025dfecf96Smrg}
10035dfecf96Smrg
10045dfecf96Smrgstatic void
10055dfecf96SmrgDEFOP_REAL_OBJECT(add)
10065dfecf96Smrg
10075dfecf96Smrgstatic void
10085dfecf96SmrgDEFOP_REAL_OBJECT(sub)
10095dfecf96Smrg
10105dfecf96Smrgstatic void
10115dfecf96SmrgDEFOP_REAL_OBJECT(div)
10125dfecf96Smrg
10135dfecf96Smrgstatic void
10145dfecf96SmrgDEFOP_REAL_OBJECT(mul)
10155dfecf96Smrg
10165dfecf96Smrg
10175dfecf96Smrg#define DEFOP_NUMBER_OBJECT(OP)						\
10185dfecf96SmrgOP##_number_object(n_number *num, LispObj *obj)				\
10195dfecf96Smrg{									\
10205dfecf96Smrg    if (num->complex) {							\
10215dfecf96Smrg	switch (OBJECT_TYPE(obj)) {					\
10225dfecf96Smrg	    case LispFixnum_t:						\
10235dfecf96Smrg	    case LispInteger_t:						\
10245dfecf96Smrg	    case LispBignum_t:						\
10255dfecf96Smrg	    case LispDFloat_t:						\
10265dfecf96Smrg	    case LispRatio_t:						\
10275dfecf96Smrg	    case LispBigratio_t:					\
10285dfecf96Smrg		n##OP##_cx_re(num, obj);				\
10295dfecf96Smrg		break;							\
10305dfecf96Smrg	    case LispComplex_t:						\
10315dfecf96Smrg		n##OP##_cx_cx(num, obj);				\
10325dfecf96Smrg		break;							\
10335dfecf96Smrg	    default:							\
10345dfecf96Smrg		fatal_object_error(obj, NOT_A_NUMBER);			\
10355dfecf96Smrg		break;							\
10365dfecf96Smrg	}								\
10375dfecf96Smrg    }									\
10385dfecf96Smrg    else {								\
10395dfecf96Smrg	switch (OBJECT_TYPE(obj)) {					\
10405dfecf96Smrg	    case LispFixnum_t:						\
10415dfecf96Smrg		switch (NRTYPE(num)) {					\
10425dfecf96Smrg		    case N_FIXNUM:					\
10435dfecf96Smrg			r##OP##_fi_fi(NREAL(num), OFI(obj));		\
10445dfecf96Smrg			break;						\
10455dfecf96Smrg		    case N_BIGNUM:					\
10465dfecf96Smrg			r##OP##_bi_fi(NREAL(num), OFI(obj));		\
10475dfecf96Smrg			break;						\
10485dfecf96Smrg		    case N_FLONUM:					\
10495dfecf96Smrg			r##OP##_flonum(NREAL(num), NRFF(num),		\
10505dfecf96Smrg				    (double)OFI(obj));			\
10515dfecf96Smrg			break;						\
10525dfecf96Smrg		    case N_FIXRATIO:					\
10535dfecf96Smrg			r##OP##_fr_fi(NREAL(num), OFI(obj));		\
10545dfecf96Smrg			break;						\
10555dfecf96Smrg		    case N_BIGRATIO:					\
10565dfecf96Smrg			r##OP##_br_fi(NREAL(num), OFI(obj));		\
10575dfecf96Smrg			break;						\
10585dfecf96Smrg		}							\
10595dfecf96Smrg		break;							\
10605dfecf96Smrg	    case LispInteger_t:						\
10615dfecf96Smrg		switch (NRTYPE(num)) {					\
10625dfecf96Smrg		    case N_FIXNUM:					\
10635dfecf96Smrg			r##OP##_fi_fi(NREAL(num), OII(obj));		\
10645dfecf96Smrg			break;						\
10655dfecf96Smrg		    case N_BIGNUM:					\
10665dfecf96Smrg			r##OP##_bi_fi(NREAL(num), OII(obj));		\
10675dfecf96Smrg			break;						\
10685dfecf96Smrg		    case N_FLONUM:					\
10695dfecf96Smrg			r##OP##_flonum(NREAL(num), NRFF(num),		\
10705dfecf96Smrg				    (double)OII(obj));			\
10715dfecf96Smrg			break;						\
10725dfecf96Smrg		    case N_FIXRATIO:					\
10735dfecf96Smrg			r##OP##_fr_fi(NREAL(num), OII(obj));		\
10745dfecf96Smrg			break;						\
10755dfecf96Smrg		    case N_BIGRATIO:					\
10765dfecf96Smrg			r##OP##_br_fi(NREAL(num), OII(obj));		\
10775dfecf96Smrg			break;						\
10785dfecf96Smrg		}							\
10795dfecf96Smrg		break;							\
10805dfecf96Smrg	    case LispBignum_t:						\
10815dfecf96Smrg		switch (NRTYPE(num)) {					\
10825dfecf96Smrg		    case N_FIXNUM:					\
10835dfecf96Smrg			r##OP##_fi_bi(NREAL(num), OBI(obj));		\
10845dfecf96Smrg			break;						\
10855dfecf96Smrg		    case N_BIGNUM:					\
10865dfecf96Smrg			r##OP##_bi_bi(NREAL(num), OBI(obj));		\
10875dfecf96Smrg			break;						\
10885dfecf96Smrg		    case N_FLONUM:					\
10895dfecf96Smrg			r##OP##_flonum(NREAL(num), NRFF(num),		\
10905dfecf96Smrg				       bi_getd(OBI(obj)));		\
10915dfecf96Smrg			break;						\
10925dfecf96Smrg		    case N_FIXRATIO:					\
10935dfecf96Smrg			r##OP##_fr_bi(NREAL(num), OBI(obj));		\
10945dfecf96Smrg			break;						\
10955dfecf96Smrg		    case N_BIGRATIO:					\
10965dfecf96Smrg			r##OP##_br_bi(NREAL(num), OBI(obj));		\
10975dfecf96Smrg			break;						\
10985dfecf96Smrg		}							\
10995dfecf96Smrg		break;							\
11005dfecf96Smrg	    case LispDFloat_t:						\
11015dfecf96Smrg		switch (NRTYPE(num)) {					\
11025dfecf96Smrg		    case N_FIXNUM:					\
11035dfecf96Smrg			r##OP##_flonum(NREAL(num), (double)NRFI(num),	\
11045dfecf96Smrg				    ODF(obj));				\
11055dfecf96Smrg			break;						\
11065dfecf96Smrg		    case N_BIGNUM:					\
11075dfecf96Smrg			r##OP##_flonum(NREAL(num), bi_getd(NRBI(num)),	\
11085dfecf96Smrg				    ODF(obj));				\
11095dfecf96Smrg			break;						\
11105dfecf96Smrg		    case N_FLONUM:					\
11115dfecf96Smrg			r##OP##_flonum(NREAL(num), NRFF(num), ODF(obj));\
11125dfecf96Smrg			break;						\
11135dfecf96Smrg		    case N_FIXRATIO:					\
11145dfecf96Smrg			r##OP##_flonum(NREAL(num),			\
11155dfecf96Smrg				    (double)NRFRN(num) /		\
11165dfecf96Smrg				    (double)NRFRD(num),			\
11175dfecf96Smrg				    ODF(obj));				\
11185dfecf96Smrg			break;						\
11195dfecf96Smrg		    case N_BIGRATIO:					\
11205dfecf96Smrg			r##OP##_flonum(NREAL(num), br_getd(NRBR(num)),	\
11215dfecf96Smrg				    ODF(obj));				\
11225dfecf96Smrg			break;						\
11235dfecf96Smrg		}							\
11245dfecf96Smrg		break;							\
11255dfecf96Smrg	    case LispRatio_t:						\
11265dfecf96Smrg		switch (NRTYPE(num)) {					\
11275dfecf96Smrg		    case N_FIXNUM:					\
11285dfecf96Smrg			r##OP##_fi_fr(NREAL(num), OFRN(obj), OFRD(obj));\
11295dfecf96Smrg			break;						\
11305dfecf96Smrg		    case N_BIGNUM:					\
11315dfecf96Smrg			r##OP##_bi_fr(NREAL(num), OFRN(obj), OFRD(obj));\
11325dfecf96Smrg			break;						\
11335dfecf96Smrg		    case N_FLONUM:					\
11345dfecf96Smrg			r##OP##_flonum(NREAL(num), NRFF(num),		\
11355dfecf96Smrg				    (double)OFRN(obj) /			\
11365dfecf96Smrg				    (double)OFRD(obj));			\
11375dfecf96Smrg			break;						\
11385dfecf96Smrg		    case N_FIXRATIO:					\
11395dfecf96Smrg			r##OP##_fr_fr(NREAL(num), OFRN(obj), OFRD(obj));\
11405dfecf96Smrg			break;						\
11415dfecf96Smrg		    case N_BIGRATIO:					\
11425dfecf96Smrg			r##OP##_br_fr(NREAL(num), OFRN(obj), OFRD(obj));\
11435dfecf96Smrg			break;						\
11445dfecf96Smrg		}							\
11455dfecf96Smrg		break;							\
11465dfecf96Smrg	    case LispBigratio_t:					\
11475dfecf96Smrg		switch (NRTYPE(num)) {					\
11485dfecf96Smrg		    case N_FIXNUM:					\
11495dfecf96Smrg			r##OP##_fi_br(NREAL(num), OBR(obj));		\
11505dfecf96Smrg			break;						\
11515dfecf96Smrg		    case N_BIGNUM:					\
11525dfecf96Smrg			r##OP##_bi_br(NREAL(num), OBR(obj));		\
11535dfecf96Smrg			break;						\
11545dfecf96Smrg		    case N_FLONUM:					\
11555dfecf96Smrg			r##OP##_flonum(NREAL(num), NRFF(num),		\
11565dfecf96Smrg				    br_getd(OBR(obj)));		\
11575dfecf96Smrg			break;						\
11585dfecf96Smrg		    case N_FIXRATIO:					\
11595dfecf96Smrg			r##OP##_fr_br(NREAL(num), OBR(obj));		\
11605dfecf96Smrg			break;						\
11615dfecf96Smrg		    case N_BIGRATIO:					\
11625dfecf96Smrg			r##OP##_br_br(NREAL(num), OBR(obj));		\
11635dfecf96Smrg			break;						\
11645dfecf96Smrg		}							\
11655dfecf96Smrg		break;							\
11665dfecf96Smrg	    case LispComplex_t:						\
11675dfecf96Smrg		n##OP##_re_cx(num, obj);				\
11685dfecf96Smrg		break;							\
11695dfecf96Smrg	    default:							\
11705dfecf96Smrg		fatal_object_error(obj, NOT_A_NUMBER);			\
11715dfecf96Smrg		break;							\
11725dfecf96Smrg	}								\
11735dfecf96Smrg    }									\
11745dfecf96Smrg}
11755dfecf96Smrg
11765dfecf96Smrgstatic void
11775dfecf96SmrgDEFOP_NUMBER_OBJECT(add)
11785dfecf96Smrg
11795dfecf96Smrgstatic void
11805dfecf96SmrgDEFOP_NUMBER_OBJECT(sub)
11815dfecf96Smrg
11825dfecf96Smrgstatic void
11835dfecf96SmrgDEFOP_NUMBER_OBJECT(div)
11845dfecf96Smrg
11855dfecf96Smrgstatic void
11865dfecf96SmrgDEFOP_NUMBER_OBJECT(mul)
11875dfecf96Smrg
11885dfecf96Smrg
11895dfecf96Smrg/************************************************************************
11905dfecf96Smrg * ABS
11915dfecf96Smrg ************************************************************************/
11925dfecf96Smrgstatic void
11935dfecf96Smrgabs_real(n_real *real)
11945dfecf96Smrg{
11955dfecf96Smrg    switch (RTYPE(real)) {
11965dfecf96Smrg	case N_FIXNUM:		rabs_fi(real);	break;
11975dfecf96Smrg	case N_BIGNUM:		rabs_bi(real);	break;
11985dfecf96Smrg	case N_FLONUM:		rabs_ff(real);	break;
11995dfecf96Smrg	case N_FIXRATIO:	rabs_fr(real);	break;
12005dfecf96Smrg	case N_BIGRATIO:	rabs_br(real);	break;
12015dfecf96Smrg    }
12025dfecf96Smrg}
12035dfecf96Smrg
12045dfecf96Smrgstatic void
12055dfecf96Smrgabs_number(n_number *num)
12065dfecf96Smrg{
12075dfecf96Smrg    if (num->complex)
12085dfecf96Smrg	nabs_cx(num);
12095dfecf96Smrg    else {
12105dfecf96Smrg	switch (NRTYPE(num)) {
12115dfecf96Smrg	    case N_FIXNUM:	rabs_fi(NREAL(num));	break;
12125dfecf96Smrg	    case N_BIGNUM:	rabs_bi(NREAL(num));	break;
12135dfecf96Smrg	    case N_FLONUM:	rabs_ff(NREAL(num));	break;
12145dfecf96Smrg	    case N_FIXRATIO:	rabs_fr(NREAL(num));	break;
12155dfecf96Smrg	    case N_BIGRATIO:	rabs_br(NREAL(num));	break;
12165dfecf96Smrg	}
12175dfecf96Smrg    }
12185dfecf96Smrg}
12195dfecf96Smrg
12205dfecf96Smrgstatic void
12215dfecf96Smrgnabs_cx(n_number *num)
12225dfecf96Smrg{
12235dfecf96Smrg    n_real temp;
12245dfecf96Smrg
12255dfecf96Smrg    abs_real(NREAL(num));
12265dfecf96Smrg    abs_real(NIMAG(num));
12275dfecf96Smrg
12285dfecf96Smrg    if (cmp_real_real(NREAL(num), NIMAG(num)) < 0) {
12295dfecf96Smrg	memcpy(&temp, NIMAG(num), sizeof(n_real));
12305dfecf96Smrg	memcpy(NIMAG(num), NREAL(num), sizeof(n_real));
12315dfecf96Smrg	memcpy(NREAL(num), &temp, sizeof(n_real));
12325dfecf96Smrg    }
12335dfecf96Smrg
12345dfecf96Smrg    if (cmp_real_real(NIMAG(num), &zero) == 0) {
12355dfecf96Smrg	num->complex = 0;
12365dfecf96Smrg	if (NITYPE(num) == N_FLONUM) {
12375dfecf96Smrg	    /* change number type */
12385dfecf96Smrg	    temp.type = N_FLONUM;
12395dfecf96Smrg	    temp.data.flonum = 1.0;
12405dfecf96Smrg	    mul_real_real(NREAL(num), &temp);
12415dfecf96Smrg	}
12425dfecf96Smrg	else
12435dfecf96Smrg	    clear_real(NIMAG(num));
12445dfecf96Smrg    }
12455dfecf96Smrg    else {
12465dfecf96Smrg	div_real_real(NIMAG(num), NREAL(num));
12475dfecf96Smrg	set_real_real(&temp, NIMAG(num));
12485dfecf96Smrg	mul_real_real(NIMAG(num), &temp);
12495dfecf96Smrg	clear_real(&temp);
12505dfecf96Smrg
12515dfecf96Smrg	add_real_real(NIMAG(num), &one);
12525dfecf96Smrg	sqrt_real(NIMAG(num));
12535dfecf96Smrg
12545dfecf96Smrg	mul_real_real(NIMAG(num), NREAL(num));
12555dfecf96Smrg	clear_real(NREAL(num));
12565dfecf96Smrg	memcpy(NREAL(num), NIMAG(num), sizeof(n_real));
12575dfecf96Smrg	num->complex = 0;
12585dfecf96Smrg    }
12595dfecf96Smrg}
12605dfecf96Smrg
12615dfecf96Smrgstatic INLINE void
12625dfecf96Smrgrabs_fi(n_real *real)
12635dfecf96Smrg{
12645dfecf96Smrg    if (RFI(real) < 0)
12655dfecf96Smrg	rneg_fi(real);
12665dfecf96Smrg}
12675dfecf96Smrg
12685dfecf96Smrgstatic INLINE void
12695dfecf96Smrgrabs_bi(n_real *real)
12705dfecf96Smrg{
12715dfecf96Smrg    if (mpi_cmpi(RBI(real), 0) < 0)
12725dfecf96Smrg	mpi_neg(RBI(real), RBI(real));
12735dfecf96Smrg}
12745dfecf96Smrg
12755dfecf96Smrgstatic INLINE void
12765dfecf96Smrgrabs_ff(n_real *real)
12775dfecf96Smrg{
12785dfecf96Smrg    if (RFF(real) < 0.0)
12795dfecf96Smrg	RFF(real) = -RFF(real);
12805dfecf96Smrg}
12815dfecf96Smrg
12825dfecf96Smrgstatic INLINE void
12835dfecf96Smrgrabs_fr(n_real *real)
12845dfecf96Smrg{
12855dfecf96Smrg    if (RFRN(real) < 0)
12865dfecf96Smrg	rneg_fr(real);
12875dfecf96Smrg}
12885dfecf96Smrg
12895dfecf96Smrgstatic INLINE void
12905dfecf96Smrgrabs_br(n_real *real)
12915dfecf96Smrg{
12925dfecf96Smrg    if (mpi_cmpi(RBRN(real), 0) < 0)
12935dfecf96Smrg	mpi_neg(RBRN(real), RBRN(real));
12945dfecf96Smrg}
12955dfecf96Smrg
12965dfecf96Smrg
12975dfecf96Smrg/************************************************************************
12985dfecf96Smrg * NEG
12995dfecf96Smrg ************************************************************************/
13005dfecf96Smrgstatic void
13015dfecf96Smrgneg_real(n_real *real)
13025dfecf96Smrg{
13035dfecf96Smrg    switch (RTYPE(real)) {
13045dfecf96Smrg	case N_FIXNUM:		rneg_fi(real);	break;
13055dfecf96Smrg	case N_BIGNUM:		rneg_bi(real);	break;
13065dfecf96Smrg	case N_FLONUM:		rneg_ff(real);	break;
13075dfecf96Smrg	case N_FIXRATIO:	rneg_fr(real);	break;
13085dfecf96Smrg	case N_BIGRATIO:	rneg_br(real);	break;
13095dfecf96Smrg    }
13105dfecf96Smrg}
13115dfecf96Smrg
13125dfecf96Smrgstatic void
13135dfecf96Smrgneg_number(n_number *num)
13145dfecf96Smrg{
13155dfecf96Smrg    if (num->complex) {
13165dfecf96Smrg	neg_real(NREAL(num));
13175dfecf96Smrg	neg_real(NIMAG(num));
13185dfecf96Smrg    }
13195dfecf96Smrg    else {
13205dfecf96Smrg	switch (NRTYPE(num)) {
13215dfecf96Smrg	    case N_FIXNUM:	rneg_fi(NREAL(num));	break;
13225dfecf96Smrg	    case N_BIGNUM:	rneg_bi(NREAL(num));	break;
13235dfecf96Smrg	    case N_FLONUM:	rneg_ff(NREAL(num));	break;
13245dfecf96Smrg	    case N_FIXRATIO:	rneg_fr(NREAL(num));	break;
13255dfecf96Smrg	    case N_BIGRATIO:	rneg_br(NREAL(num));	break;
13265dfecf96Smrg	}
13275dfecf96Smrg    }
13285dfecf96Smrg}
13295dfecf96Smrg
13305dfecf96Smrgstatic void
13315dfecf96Smrgrneg_fi(n_real *real)
13325dfecf96Smrg{
13335dfecf96Smrg    if (RFI(real) == MINSLONG) {
13345dfecf96Smrg	mpi *bigi = XALLOC(mpi);
13355dfecf96Smrg
13365dfecf96Smrg	mpi_init(bigi);
13375dfecf96Smrg	mpi_seti(bigi, RFI(real));
13385dfecf96Smrg	mpi_neg(bigi, bigi);
13395dfecf96Smrg	RTYPE(real) = N_BIGNUM;
13405dfecf96Smrg	RBI(real) = bigi;
13415dfecf96Smrg    }
13425dfecf96Smrg    else
13435dfecf96Smrg	RFI(real) = -RFI(real);
13445dfecf96Smrg}
13455dfecf96Smrg
13465dfecf96Smrgstatic INLINE void
13475dfecf96Smrgrneg_bi(n_real *real)
13485dfecf96Smrg{
13495dfecf96Smrg    mpi_neg(RBI(real), RBI(real));
13505dfecf96Smrg}
13515dfecf96Smrg
13525dfecf96Smrgstatic INLINE void
13535dfecf96Smrgrneg_ff(n_real *real)
13545dfecf96Smrg{
13555dfecf96Smrg    RFF(real) = -RFF(real);
13565dfecf96Smrg}
13575dfecf96Smrg
13585dfecf96Smrgstatic void
13595dfecf96Smrgrneg_fr(n_real *real)
13605dfecf96Smrg{
13615dfecf96Smrg    if (RFRN(real) == MINSLONG) {
13625dfecf96Smrg	mpr *bigr = XALLOC(mpr);
13635dfecf96Smrg
13645dfecf96Smrg	mpr_init(bigr);
13655dfecf96Smrg	mpr_seti(bigr, RFRN(real), RFRD(real));
13665dfecf96Smrg	mpi_neg(mpr_num(bigr), mpr_num(bigr));
13675dfecf96Smrg	RTYPE(real) = N_BIGRATIO;
13685dfecf96Smrg	RBR(real) = bigr;
13695dfecf96Smrg    }
13705dfecf96Smrg    else
13715dfecf96Smrg	RFRN(real) = -RFRN(real);
13725dfecf96Smrg}
13735dfecf96Smrg
13745dfecf96Smrgstatic INLINE void
13755dfecf96Smrgrneg_br(n_real *real)
13765dfecf96Smrg{
13775dfecf96Smrg    mpi_neg(RBRN(real), RBRN(real));
13785dfecf96Smrg}
13795dfecf96Smrg
13805dfecf96Smrg
13815dfecf96Smrg/************************************************************************
13825dfecf96Smrg * SQRT
13835dfecf96Smrg ************************************************************************/
13845dfecf96Smrgstatic void
13855dfecf96Smrgsqrt_real(n_real *real)
13865dfecf96Smrg{
13875dfecf96Smrg    switch (RTYPE(real)) {
13885dfecf96Smrg	case N_FIXNUM:
13895dfecf96Smrg	case N_BIGNUM:
13905dfecf96Smrg	    rsqrt_xi(real);
13915dfecf96Smrg	    break;
13925dfecf96Smrg	case N_FLONUM:
13935dfecf96Smrg	    rsqrt_ff(real);
13945dfecf96Smrg	    break;
13955dfecf96Smrg	case N_FIXRATIO:
13965dfecf96Smrg	case N_BIGRATIO:
13975dfecf96Smrg	    rsqrt_xr(real);
13985dfecf96Smrg	    break;
13995dfecf96Smrg    }
14005dfecf96Smrg}
14015dfecf96Smrg
14025dfecf96Smrgstatic void
14035dfecf96Smrgsqrt_number(n_number *num)
14045dfecf96Smrg{
14055dfecf96Smrg    if (num->complex)
14065dfecf96Smrg	nsqrt_cx(num);
14075dfecf96Smrg    else {
14085dfecf96Smrg	switch (NRTYPE(num)) {
14095dfecf96Smrg	    case N_FIXNUM:
14105dfecf96Smrg	    case N_BIGNUM:
14115dfecf96Smrg		nsqrt_xi(num);
14125dfecf96Smrg		break;
14135dfecf96Smrg	    case N_FLONUM:
14145dfecf96Smrg		nsqrt_ff(num);
14155dfecf96Smrg		break;
14165dfecf96Smrg	    case N_FIXRATIO:
14175dfecf96Smrg	    case N_BIGRATIO:
14185dfecf96Smrg		nsqrt_xr(num);
14195dfecf96Smrg		break;
14205dfecf96Smrg	}
14215dfecf96Smrg    }
14225dfecf96Smrg}
14235dfecf96Smrg
14245dfecf96Smrgstatic void
14255dfecf96Smrgrsqrt_xi(n_real *real)
14265dfecf96Smrg{
14275dfecf96Smrg    int exact;
14285dfecf96Smrg    mpi bignum;
14295dfecf96Smrg
14305dfecf96Smrg    if (cmp_real_real(real, &zero) < 0)
14315dfecf96Smrg	fatal_error(FLOATING_POINT_EXCEPTION);
14325dfecf96Smrg
14335dfecf96Smrg    mpi_init(&bignum);
14345dfecf96Smrg    if (RTYPE(real) == N_BIGNUM)
14355dfecf96Smrg	exact = mpi_sqrt(&bignum, RBI(real));
14365dfecf96Smrg    else {
14375dfecf96Smrg	mpi tmp;
14385dfecf96Smrg
14395dfecf96Smrg	mpi_init(&tmp);
14405dfecf96Smrg	mpi_seti(&tmp, RFI(real));
14415dfecf96Smrg	exact = mpi_sqrt(&bignum, &tmp);
14425dfecf96Smrg	mpi_clear(&tmp);
14435dfecf96Smrg    }
14445dfecf96Smrg    if (exact) {
14455dfecf96Smrg	if (RTYPE(real) == N_BIGNUM) {
14465dfecf96Smrg	    mpi_set(RBI(real), &bignum);
14475dfecf96Smrg	    rbi_canonicalize(real);
14485dfecf96Smrg	}
14495dfecf96Smrg	else
14505dfecf96Smrg	    RFI(real) = mpi_geti(&bignum);
14515dfecf96Smrg    }
14525dfecf96Smrg    else {
14535dfecf96Smrg	double value;
14545dfecf96Smrg
14555dfecf96Smrg	if (RTYPE(real) == N_BIGNUM) {
14565dfecf96Smrg	    value = bi_getd(RBI(real));
14575dfecf96Smrg	    RCLEAR_BI(real);
14585dfecf96Smrg	}
14595dfecf96Smrg	else
14605dfecf96Smrg	    value = (double)RFI(real);
14615dfecf96Smrg
14625dfecf96Smrg	value = sqrt(value);
14635dfecf96Smrg	RTYPE(real) = N_FLONUM;
14645dfecf96Smrg	RFF(real) = value;
14655dfecf96Smrg    }
14665dfecf96Smrg    mpi_clear(&bignum);
14675dfecf96Smrg}
14685dfecf96Smrg
14695dfecf96Smrgstatic void
14705dfecf96Smrgrsqrt_xr(n_real *real)
14715dfecf96Smrg{
14725dfecf96Smrg    n_real num, den;
14735dfecf96Smrg
14745dfecf96Smrg    if (cmp_real_real(real, &zero) < 0)
14755dfecf96Smrg	fatal_error(FLOATING_POINT_EXCEPTION);
14765dfecf96Smrg
14775dfecf96Smrg    if (RTYPE(real) == N_FIXRATIO) {
14785dfecf96Smrg	num.type = den.type = N_FIXNUM;
14795dfecf96Smrg	num.data.fixnum = RFRN(real);
14805dfecf96Smrg	den.data.fixnum = RFRD(real);
14815dfecf96Smrg    }
14825dfecf96Smrg    else {
14835dfecf96Smrg	mpi *bignum;
14845dfecf96Smrg
14855dfecf96Smrg	if (mpi_fiti(RBRN(real))) {
14865dfecf96Smrg	    num.type = N_FIXNUM;
14875dfecf96Smrg	    num.data.fixnum = mpi_geti(RBRN(real));
14885dfecf96Smrg	}
14895dfecf96Smrg	else {
14905dfecf96Smrg	    bignum = XALLOC(mpi);
14915dfecf96Smrg	    mpi_init(bignum);
14925dfecf96Smrg	    mpi_set(bignum, RBRN(real));
14935dfecf96Smrg	    num.type = N_BIGNUM;
14945dfecf96Smrg	    num.data.bignum = bignum;
14955dfecf96Smrg	}
14965dfecf96Smrg
14975dfecf96Smrg	if (mpi_fiti(RBRD(real))) {
14985dfecf96Smrg	    den.type = N_FIXNUM;
14995dfecf96Smrg	    den.data.fixnum = mpi_geti(RBRD(real));
15005dfecf96Smrg	}
15015dfecf96Smrg	else {
15025dfecf96Smrg	    bignum = XALLOC(mpi);
15035dfecf96Smrg	    mpi_init(bignum);
15045dfecf96Smrg	    mpi_set(bignum, RBRD(real));
15055dfecf96Smrg	    den.type = N_BIGNUM;
15065dfecf96Smrg	    den.data.bignum = bignum;
15075dfecf96Smrg	}
15085dfecf96Smrg    }
15095dfecf96Smrg
15105dfecf96Smrg    rsqrt_xi(&num);
15115dfecf96Smrg    rsqrt_xi(&den);
15125dfecf96Smrg
15135dfecf96Smrg    clear_real(real);
15145dfecf96Smrg    memcpy(real, &num, sizeof(n_real));
15155dfecf96Smrg    div_real_real(real, &den);
15165dfecf96Smrg    clear_real(&den);
15175dfecf96Smrg}
15185dfecf96Smrg
15195dfecf96Smrgstatic void
15205dfecf96Smrgrsqrt_ff(n_real *real)
15215dfecf96Smrg{
15225dfecf96Smrg    if (RFF(real) < 0.0)
15235dfecf96Smrg	fatal_error(FLOATING_POINT_EXCEPTION);
15245dfecf96Smrg    RFF(real) = sqrt(RFF(real));
15255dfecf96Smrg}
15265dfecf96Smrg
15275dfecf96Smrg
15285dfecf96Smrgstatic void
15295dfecf96Smrgnsqrt_cx(n_number *num)
15305dfecf96Smrg{
15315dfecf96Smrg    n_number mag;
15325dfecf96Smrg    n_real *real, *imag;
15335dfecf96Smrg
15345dfecf96Smrg    real = &(mag.real);
15355dfecf96Smrg    imag = &(mag.imag);
15365dfecf96Smrg    set_real_real(real, NREAL(num));
15375dfecf96Smrg    set_real_real(imag, NIMAG(num));
15385dfecf96Smrg    mag.complex = 1;
15395dfecf96Smrg
15405dfecf96Smrg    nabs_cx(&mag);	/* this will free the imag part data */
15415dfecf96Smrg    if (cmp_real_real(real, &zero) == 0) {
15425dfecf96Smrg	clear_number(num);
15435dfecf96Smrg	memcpy(NREAL(num), real, sizeof(n_real));
15445dfecf96Smrg	clear_real(real);
15455dfecf96Smrg	num->complex = 0;
15465dfecf96Smrg	return;
15475dfecf96Smrg    }
15485dfecf96Smrg    else if (cmp_real_real(NREAL(num), &zero) > 0) {
15495dfecf96Smrg	/* R = sqrt((mag + Ra) / 2) */
15505dfecf96Smrg	add_real_real(NREAL(num), real);
15515dfecf96Smrg	clear_real(real);
15525dfecf96Smrg	div_real_real(NREAL(num), &two);
15535dfecf96Smrg	sqrt_real(NREAL(num));
15545dfecf96Smrg
15555dfecf96Smrg	/* I = Ia / R / 2 */
15565dfecf96Smrg	div_real_real(NIMAG(num), NREAL(num));
15575dfecf96Smrg	div_real_real(NIMAG(num), &two);
15585dfecf96Smrg    }
15595dfecf96Smrg    else {
15605dfecf96Smrg	/* remember old imag part */
15615dfecf96Smrg	memcpy(imag, NIMAG(num), sizeof(n_real));
15625dfecf96Smrg
15635dfecf96Smrg	/* I = sqrt((mag - Ra) / 2) */
15645dfecf96Smrg	memcpy(NIMAG(num), real, sizeof(n_real));
15655dfecf96Smrg	sub_real_real(NIMAG(num), NREAL(num));
15665dfecf96Smrg	div_real_real(NIMAG(num), &two);
15675dfecf96Smrg	sqrt_real(NIMAG(num));
15685dfecf96Smrg	if (cmp_real_real(imag, &zero) < 0)
15695dfecf96Smrg	    neg_real(NIMAG(num));
15705dfecf96Smrg
15715dfecf96Smrg	/* R = Ia / I / 2 */
15725dfecf96Smrg	clear_real(NREAL(num));
15735dfecf96Smrg	/* start with old imag part */
15745dfecf96Smrg	memcpy(NREAL(num), imag, sizeof(n_real));
15755dfecf96Smrg	div_real_real(NREAL(num), NIMAG(num));
15765dfecf96Smrg	div_real_real(NREAL(num), &two);
15775dfecf96Smrg    }
15785dfecf96Smrg
15795dfecf96Smrg    ncx_canonicalize(num);
15805dfecf96Smrg}
15815dfecf96Smrg
15825dfecf96Smrgstatic void
15835dfecf96Smrgnsqrt_xi(n_number *num)
15845dfecf96Smrg{
15855dfecf96Smrg    if (cmp_real_real(NREAL(num), &zero) < 0) {
15865dfecf96Smrg	memcpy(NIMAG(num), NREAL(num), sizeof(n_real));
15875dfecf96Smrg	neg_real(NIMAG(num));
15885dfecf96Smrg	rsqrt_xi(NIMAG(num));
15895dfecf96Smrg	NRTYPE(num) = N_FIXNUM;
15905dfecf96Smrg	NRFI(num) = 0;
15915dfecf96Smrg	num->complex = 1;
15925dfecf96Smrg    }
15935dfecf96Smrg    else
15945dfecf96Smrg	rsqrt_xi(NREAL(num));
15955dfecf96Smrg}
15965dfecf96Smrg
15975dfecf96Smrgstatic void
15985dfecf96Smrgnsqrt_ff(n_number *num)
15995dfecf96Smrg{
16005dfecf96Smrg    double value;
16015dfecf96Smrg
16025dfecf96Smrg    if (NRFF(num) < 0.0) {
16035dfecf96Smrg	value = sqrt(-NRFF(num));
16045dfecf96Smrg
16055dfecf96Smrg	NITYPE(num) = N_FLONUM;
16065dfecf96Smrg	NIFF(num) = value;
16075dfecf96Smrg	NRTYPE(num) = N_FIXNUM;
16085dfecf96Smrg	NRFI(num) = 0;
16095dfecf96Smrg	num->complex = 1;
16105dfecf96Smrg    }
16115dfecf96Smrg    else {
16125dfecf96Smrg	value = sqrt(NRFF(num));
16135dfecf96Smrg	NRFF(num) = value;
16145dfecf96Smrg    }
16155dfecf96Smrg}
16165dfecf96Smrg
16175dfecf96Smrgstatic void
16185dfecf96Smrgnsqrt_xr(n_number *num)
16195dfecf96Smrg{
16205dfecf96Smrg    if (cmp_real_real(NREAL(num), &zero) < 0) {
16215dfecf96Smrg	memcpy(NIMAG(num), NREAL(num), sizeof(n_real));
16225dfecf96Smrg	neg_real(NIMAG(num));
16235dfecf96Smrg	rsqrt_xr(NIMAG(num));
16245dfecf96Smrg	NRTYPE(num) = N_FIXNUM;
16255dfecf96Smrg	NRFI(num) = 0;
16265dfecf96Smrg	num->complex = 1;
16275dfecf96Smrg    }
16285dfecf96Smrg    else
16295dfecf96Smrg	rsqrt_xr(NREAL(num));
16305dfecf96Smrg}
16315dfecf96Smrg
16325dfecf96Smrg
16335dfecf96Smrg/************************************************************************
16345dfecf96Smrg * MOD
16355dfecf96Smrg ************************************************************************/
16365dfecf96Smrgstatic void
16375dfecf96Smrgmod_real_real(n_real *real, n_real *val)
16385dfecf96Smrg{
16395dfecf96Smrg    /* Assume both operands are integers */
16405dfecf96Smrg    switch (RTYPE(real)) {
16415dfecf96Smrg	case N_FIXNUM:
16425dfecf96Smrg	    switch (RTYPE(val)) {
16435dfecf96Smrg		case N_FIXNUM:
16445dfecf96Smrg		    rmod_fi_fi(real, RFI(val));
16455dfecf96Smrg		    break;
16465dfecf96Smrg		case N_BIGNUM:
16475dfecf96Smrg		    rmod_fi_bi(real, RBI(val));
16485dfecf96Smrg		    break;
16495dfecf96Smrg	    }
16505dfecf96Smrg	    break;
16515dfecf96Smrg	case N_BIGNUM:
16525dfecf96Smrg	    switch (RTYPE(val)) {
16535dfecf96Smrg		case N_FIXNUM:
16545dfecf96Smrg		    rmod_bi_fi(real, RFI(val));
16555dfecf96Smrg		    break;
16565dfecf96Smrg		case N_BIGNUM:
16575dfecf96Smrg		    rmod_bi_bi(real, RBI(val));
16585dfecf96Smrg		    break;
16595dfecf96Smrg	    }
16605dfecf96Smrg	    break;
16615dfecf96Smrg    }
16625dfecf96Smrg}
16635dfecf96Smrg
16645dfecf96Smrgstatic void
16655dfecf96Smrgmod_real_object(n_real *real, LispObj *obj)
16665dfecf96Smrg{
16675dfecf96Smrg    switch (RTYPE(real)) {
16685dfecf96Smrg	case N_FIXNUM:
16695dfecf96Smrg	    switch (OBJECT_TYPE(obj)) {
16705dfecf96Smrg		case LispFixnum_t:
16715dfecf96Smrg		    rmod_fi_fi(real, OFI(obj));
16725dfecf96Smrg		    return;
16735dfecf96Smrg		case LispInteger_t:
16745dfecf96Smrg		    rmod_fi_fi(real, OII(obj));
16755dfecf96Smrg		    return;
16765dfecf96Smrg		case LispBignum_t:
16775dfecf96Smrg		    rmod_fi_bi(real, OBI(obj));
16785dfecf96Smrg		    return;
16795dfecf96Smrg		default:
16805dfecf96Smrg		    break;
16815dfecf96Smrg	    }
16825dfecf96Smrg	    break;
16835dfecf96Smrg	case N_BIGNUM:
16845dfecf96Smrg	    switch (OBJECT_TYPE(obj)) {
16855dfecf96Smrg		case LispFixnum_t:
16865dfecf96Smrg		    rmod_bi_fi(real, OFI(obj));
16875dfecf96Smrg		    return;
16885dfecf96Smrg		case LispInteger_t:
16895dfecf96Smrg		    rmod_bi_fi(real, OII(obj));
16905dfecf96Smrg		    return;
16915dfecf96Smrg		case LispBignum_t:
16925dfecf96Smrg		    rmod_bi_bi(real, OBI(obj));
16935dfecf96Smrg		    return;
16945dfecf96Smrg		default:
16955dfecf96Smrg		    break;
16965dfecf96Smrg	    }
16975dfecf96Smrg	    break;
16985dfecf96Smrg	/* Assume the n_real object is an integer */
16995dfecf96Smrg    }
17005dfecf96Smrg    fatal_object_error(obj, NOT_AN_INTEGER);
17015dfecf96Smrg}
17025dfecf96Smrg
17035dfecf96Smrgstatic void
17045dfecf96Smrgrmod_fi_fi(n_real *real, long fi)
17055dfecf96Smrg{
17065dfecf96Smrg    if (fi == 0)
17075dfecf96Smrg	fatal_error(DIVIDE_BY_ZERO);
17085dfecf96Smrg
17095dfecf96Smrg    if ((RFI(real) < 0) ^ (fi < 0))
17105dfecf96Smrg	RFI(real) = (RFI(real) % fi) + fi;
17115dfecf96Smrg    else if (RFI(real) == MINSLONG || fi == MINSLONG) {
17125dfecf96Smrg	mpi bignum;
17135dfecf96Smrg
17145dfecf96Smrg	mpi_init(&bignum);
17155dfecf96Smrg	mpi_seti(&bignum, RFI(real));
17165dfecf96Smrg	RFI(real) = mpi_modi(&bignum, fi);
17175dfecf96Smrg	mpi_clear(&bignum);
17185dfecf96Smrg    }
17195dfecf96Smrg    else
17205dfecf96Smrg	RFI(real) = RFI(real) % fi;
17215dfecf96Smrg}
17225dfecf96Smrg
17235dfecf96Smrgstatic void
17245dfecf96Smrgrmod_fi_bi(n_real *real, mpi *bignum)
17255dfecf96Smrg{
17265dfecf96Smrg    mpi *bigi;
17275dfecf96Smrg
17285dfecf96Smrg    if (mpi_cmpi(bignum, 0) == 0)
17295dfecf96Smrg	fatal_error(DIVIDE_BY_ZERO);
17305dfecf96Smrg
17315dfecf96Smrg    bigi = XALLOC(mpi);
17325dfecf96Smrg    mpi_init(bigi);
17335dfecf96Smrg    mpi_seti(bigi, RFI(real));
17345dfecf96Smrg    mpi_mod(bigi, bigi, bignum);
17355dfecf96Smrg    RTYPE(real) = N_BIGNUM;
17365dfecf96Smrg    RBI(real) = bigi;
17375dfecf96Smrg    rbi_canonicalize(real);
17385dfecf96Smrg}
17395dfecf96Smrg
17405dfecf96Smrgstatic void
17415dfecf96Smrgrmod_bi_fi(n_real *real, long fi)
17425dfecf96Smrg{
17435dfecf96Smrg    mpi iop;
17445dfecf96Smrg
17455dfecf96Smrg    if (fi == 0)
17465dfecf96Smrg	fatal_error(DIVIDE_BY_ZERO);
17475dfecf96Smrg
17485dfecf96Smrg    mpi_init(&iop);
17495dfecf96Smrg    mpi_seti(&iop, fi);
17505dfecf96Smrg    mpi_mod(RBI(real), RBI(real), &iop);
17515dfecf96Smrg    mpi_clear(&iop);
17525dfecf96Smrg    rbi_canonicalize(real);
17535dfecf96Smrg}
17545dfecf96Smrg
17555dfecf96Smrgstatic void
17565dfecf96Smrgrmod_bi_bi(n_real *real, mpi *bignum)
17575dfecf96Smrg{
17585dfecf96Smrg    if (mpi_cmpi(bignum, 0) == 0)
17595dfecf96Smrg	fatal_error(DIVIDE_BY_ZERO);
17605dfecf96Smrg
17615dfecf96Smrg    mpi_mod(RBI(real), RBI(real), bignum);
17625dfecf96Smrg    rbi_canonicalize(real);
17635dfecf96Smrg}
17645dfecf96Smrg
17655dfecf96Smrg/************************************************************************
17665dfecf96Smrg * REM
17675dfecf96Smrg ************************************************************************/
17685dfecf96Smrgstatic void
17695dfecf96Smrgrem_real_object(n_real *real, LispObj *obj)
17705dfecf96Smrg{
17715dfecf96Smrg    switch (RTYPE(real)) {
17725dfecf96Smrg	case N_FIXNUM:
17735dfecf96Smrg	    switch (OBJECT_TYPE(obj)) {
17745dfecf96Smrg		case LispFixnum_t:
17755dfecf96Smrg		    rrem_fi_fi(real, OFI(obj));
17765dfecf96Smrg		    return;
17775dfecf96Smrg		case LispInteger_t:
17785dfecf96Smrg		    rrem_fi_fi(real, OII(obj));
17795dfecf96Smrg		    return;
17805dfecf96Smrg		case LispBignum_t:
17815dfecf96Smrg		    rrem_fi_bi(real, OBI(obj));
17825dfecf96Smrg		    return;
17835dfecf96Smrg		default:
17845dfecf96Smrg		    break;
17855dfecf96Smrg	    }
17865dfecf96Smrg	    break;
17875dfecf96Smrg	case N_BIGNUM:
17885dfecf96Smrg	    switch (OBJECT_TYPE(obj)) {
17895dfecf96Smrg		case LispFixnum_t:
17905dfecf96Smrg		    rrem_bi_fi(real, OFI(obj));
17915dfecf96Smrg		    return;
17925dfecf96Smrg		case LispInteger_t:
17935dfecf96Smrg		    rrem_bi_fi(real, OII(obj));
17945dfecf96Smrg		    return;
17955dfecf96Smrg		case LispBignum_t:
17965dfecf96Smrg		    rrem_bi_bi(real, OBI(obj));
17975dfecf96Smrg		    return;
17985dfecf96Smrg		default:
17995dfecf96Smrg		    break;
18005dfecf96Smrg	    }
18015dfecf96Smrg	    break;
18025dfecf96Smrg	/* Assume the n_real object is an integer */
18035dfecf96Smrg    }
18045dfecf96Smrg    fatal_object_error(obj, NOT_AN_INTEGER);
18055dfecf96Smrg}
18065dfecf96Smrg
18075dfecf96Smrgstatic void
18085dfecf96Smrgrrem_fi_fi(n_real *real, long fi)
18095dfecf96Smrg{
18105dfecf96Smrg    if (fi == 0)
18115dfecf96Smrg	fatal_error(DIVIDE_BY_ZERO);
18125dfecf96Smrg
18135dfecf96Smrg    if (RFI(real) == MINSLONG || fi == MINSLONG) {
18145dfecf96Smrg	mpi bignum;
18155dfecf96Smrg
18165dfecf96Smrg	mpi_init(&bignum);
18175dfecf96Smrg	mpi_seti(&bignum, RFI(real));
18185dfecf96Smrg	RFI(real) = mpi_remi(&bignum, fi);
18195dfecf96Smrg	mpi_clear(&bignum);
18205dfecf96Smrg    }
18215dfecf96Smrg    else
18225dfecf96Smrg	RFI(real) = RFI(real) % fi;
18235dfecf96Smrg}
18245dfecf96Smrg
18255dfecf96Smrgstatic void
18265dfecf96Smrgrrem_fi_bi(n_real *real, mpi *bignum)
18275dfecf96Smrg{
18285dfecf96Smrg    mpi *bigi;
18295dfecf96Smrg
18305dfecf96Smrg    if (mpi_cmpi(bignum, 0) == 0)
18315dfecf96Smrg	fatal_error(DIVIDE_BY_ZERO);
18325dfecf96Smrg
18335dfecf96Smrg    bigi = XALLOC(mpi);
18345dfecf96Smrg    mpi_init(bigi);
18355dfecf96Smrg    mpi_seti(bigi, RFI(real));
18365dfecf96Smrg    mpi_rem(bigi, bigi, bignum);
18375dfecf96Smrg    RTYPE(real) = N_BIGNUM;
18385dfecf96Smrg    RBI(real) = bigi;
18395dfecf96Smrg    rbi_canonicalize(real);
18405dfecf96Smrg}
18415dfecf96Smrg
18425dfecf96Smrgstatic void
18435dfecf96Smrgrrem_bi_fi(n_real *real, long fi)
18445dfecf96Smrg{
18455dfecf96Smrg    mpi iop;
18465dfecf96Smrg
18475dfecf96Smrg    if (fi == 0)
18485dfecf96Smrg	fatal_error(DIVIDE_BY_ZERO);
18495dfecf96Smrg
18505dfecf96Smrg    mpi_init(&iop);
18515dfecf96Smrg    mpi_seti(&iop, fi);
18525dfecf96Smrg    mpi_rem(RBI(real), RBI(real), &iop);
18535dfecf96Smrg    mpi_clear(&iop);
18545dfecf96Smrg    rbi_canonicalize(real);
18555dfecf96Smrg}
18565dfecf96Smrg
18575dfecf96Smrgstatic void
18585dfecf96Smrgrrem_bi_bi(n_real *real, mpi *bignum)
18595dfecf96Smrg{
18605dfecf96Smrg    if (mpi_cmpi(bignum, 0) == 0)
18615dfecf96Smrg	fatal_error(DIVIDE_BY_ZERO);
18625dfecf96Smrg
18635dfecf96Smrg    mpi_rem(RBI(real), RBI(real), bignum);
18645dfecf96Smrg    rbi_canonicalize(real);
18655dfecf96Smrg}
18665dfecf96Smrg
18675dfecf96Smrg
18685dfecf96Smrg/************************************************************************
18695dfecf96Smrg * GCD
18705dfecf96Smrg ************************************************************************/
18715dfecf96Smrgstatic void
18725dfecf96Smrggcd_real_object(n_real *real, LispObj *obj)
18735dfecf96Smrg{
18745dfecf96Smrg    if (!INTEGERP(obj))
18755dfecf96Smrg	fatal_object_error(obj, NOT_AN_INTEGER);
18765dfecf96Smrg
18775dfecf96Smrg    /* check for zero operand */
18785dfecf96Smrg    if (cmp_real_real(real, &zero) == 0)
18795dfecf96Smrg	set_real_object(real, obj);
18805dfecf96Smrg    else if (cmp_real_object(&zero, obj) != 0) {
18815dfecf96Smrg	n_real rest, temp;
18825dfecf96Smrg
18835dfecf96Smrg	set_real_object(&rest, obj);
18845dfecf96Smrg	for (;;) {
18855dfecf96Smrg	    mod_real_real(&rest, real);
18865dfecf96Smrg	    if (cmp_real_real(&rest, &zero) == 0)
18875dfecf96Smrg		break;
18885dfecf96Smrg	    memcpy(&temp, real, sizeof(n_real));
18895dfecf96Smrg	    memcpy(real, &rest, sizeof(n_real));
18905dfecf96Smrg	    memcpy(&rest, &temp, sizeof(n_real));
18915dfecf96Smrg	}
18925dfecf96Smrg	clear_real(&rest);
18935dfecf96Smrg    }
18945dfecf96Smrg}
18955dfecf96Smrg
18965dfecf96Smrg/************************************************************************
18975dfecf96Smrg * AND
18985dfecf96Smrg ************************************************************************/
18995dfecf96Smrgstatic void
19005dfecf96Smrgand_real_object(n_real *real, LispObj *obj)
19015dfecf96Smrg{
19025dfecf96Smrg    mpi *bigi, iop;
19035dfecf96Smrg
19045dfecf96Smrg    switch (OBJECT_TYPE(obj)) {
19055dfecf96Smrg	case LispFixnum_t:
19065dfecf96Smrg	    switch (RTYPE(real)) {
19075dfecf96Smrg		case N_FIXNUM:
19085dfecf96Smrg		    RFI(real) &= OFI(obj);
19095dfecf96Smrg		    break;
19105dfecf96Smrg		case N_BIGNUM:
19115dfecf96Smrg		    mpi_init(&iop);
19125dfecf96Smrg		    mpi_seti(&iop, OFI(obj));
19135dfecf96Smrg		    mpi_and(RBI(real), RBI(real), &iop);
19145dfecf96Smrg		    mpi_clear(&iop);
19155dfecf96Smrg		    rbi_canonicalize(real);
19165dfecf96Smrg		    break;
19175dfecf96Smrg	    }
19185dfecf96Smrg	    break;
19195dfecf96Smrg	case LispInteger_t:
19205dfecf96Smrg	    switch (RTYPE(real)) {
19215dfecf96Smrg		case N_FIXNUM:
19225dfecf96Smrg		    RFI(real) &= OII(obj);
19235dfecf96Smrg		    break;
19245dfecf96Smrg		case N_BIGNUM:
19255dfecf96Smrg		    mpi_init(&iop);
19265dfecf96Smrg		    mpi_seti(&iop, OII(obj));
19275dfecf96Smrg		    mpi_and(RBI(real), RBI(real), &iop);
19285dfecf96Smrg		    mpi_clear(&iop);
19295dfecf96Smrg		    rbi_canonicalize(real);
19305dfecf96Smrg		    break;
19315dfecf96Smrg	    }
19325dfecf96Smrg	    break;
19335dfecf96Smrg	case LispBignum_t:
19345dfecf96Smrg	    switch (RTYPE(real)) {
19355dfecf96Smrg		case N_FIXNUM:
19365dfecf96Smrg		    bigi = XALLOC(mpi);
19375dfecf96Smrg		    mpi_init(bigi);
19385dfecf96Smrg		    mpi_seti(bigi, RFI(real));
19395dfecf96Smrg		    mpi_and(bigi, bigi, OBI(obj));
19405dfecf96Smrg		    RTYPE(real) = N_BIGNUM;
19415dfecf96Smrg		    RBI(real) = bigi;
19425dfecf96Smrg		    rbi_canonicalize(real);
19435dfecf96Smrg		    break;
19445dfecf96Smrg		case N_BIGNUM:
19455dfecf96Smrg		    mpi_and(RBI(real), RBI(real), OBI(obj));
19465dfecf96Smrg		    rbi_canonicalize(real);
19475dfecf96Smrg		    break;
19485dfecf96Smrg	    }
19495dfecf96Smrg	    break;
19505dfecf96Smrg	default:
19515dfecf96Smrg	    fatal_object_error(obj, NOT_AN_INTEGER);
19525dfecf96Smrg	    break;
19535dfecf96Smrg    }
19545dfecf96Smrg}
19555dfecf96Smrg
19565dfecf96Smrg
19575dfecf96Smrg/************************************************************************
19585dfecf96Smrg * EQV
19595dfecf96Smrg ************************************************************************/
19605dfecf96Smrgstatic void
19615dfecf96Smrgeqv_real_object(n_real *real, LispObj *obj)
19625dfecf96Smrg{
19635dfecf96Smrg    mpi *bigi, iop;
19645dfecf96Smrg
19655dfecf96Smrg    switch (OBJECT_TYPE(obj)) {
19665dfecf96Smrg	case LispFixnum_t:
19675dfecf96Smrg	    switch (RTYPE(real)) {
19685dfecf96Smrg		case N_FIXNUM:
19695dfecf96Smrg		    RFI(real) ^= ~OFI(obj);
19705dfecf96Smrg		    break;
19715dfecf96Smrg		case N_BIGNUM:
19725dfecf96Smrg		    mpi_init(&iop);
19735dfecf96Smrg		    mpi_seti(&iop, OFI(obj));
19745dfecf96Smrg		    mpi_com(&iop, &iop);
19755dfecf96Smrg		    mpi_xor(RBI(real), RBI(real), &iop);
19765dfecf96Smrg		    mpi_clear(&iop);
19775dfecf96Smrg		    rbi_canonicalize(real);
19785dfecf96Smrg		    break;
19795dfecf96Smrg	    }
19805dfecf96Smrg	    break;
19815dfecf96Smrg	case LispInteger_t:
19825dfecf96Smrg	    switch (RTYPE(real)) {
19835dfecf96Smrg		case N_FIXNUM:
19845dfecf96Smrg		    RFI(real) ^= ~OII(obj);
19855dfecf96Smrg		    break;
19865dfecf96Smrg		case N_BIGNUM:
19875dfecf96Smrg		    mpi_init(&iop);
19885dfecf96Smrg		    mpi_seti(&iop, OII(obj));
19895dfecf96Smrg		    mpi_com(&iop, &iop);
19905dfecf96Smrg		    mpi_xor(RBI(real), RBI(real), &iop);
19915dfecf96Smrg		    mpi_clear(&iop);
19925dfecf96Smrg		    rbi_canonicalize(real);
19935dfecf96Smrg		    break;
19945dfecf96Smrg	    }
19955dfecf96Smrg	    break;
19965dfecf96Smrg	case LispBignum_t:
19975dfecf96Smrg	    switch (RTYPE(real)) {
19985dfecf96Smrg		case N_FIXNUM:
19995dfecf96Smrg		    bigi = XALLOC(mpi);
20005dfecf96Smrg		    mpi_init(bigi);
20015dfecf96Smrg		    mpi_seti(bigi, RFI(real));
20025dfecf96Smrg		    mpi_com(bigi, bigi);
20035dfecf96Smrg		    mpi_xor(bigi, bigi, OBI(obj));
20045dfecf96Smrg		    RTYPE(real) = N_BIGNUM;
20055dfecf96Smrg		    RBI(real) = bigi;
20065dfecf96Smrg		    rbi_canonicalize(real);
20075dfecf96Smrg		    break;
20085dfecf96Smrg		case N_BIGNUM:
20095dfecf96Smrg		    mpi_com(RBI(real), RBI(real));
20105dfecf96Smrg		    mpi_xor(RBI(real), RBI(real), OBI(obj));
20115dfecf96Smrg		    rbi_canonicalize(real);
20125dfecf96Smrg		    break;
20135dfecf96Smrg	    }
20145dfecf96Smrg	    break;
20155dfecf96Smrg	default:
20165dfecf96Smrg	    fatal_object_error(obj, NOT_AN_INTEGER);
20175dfecf96Smrg	    break;
20185dfecf96Smrg    }
20195dfecf96Smrg}
20205dfecf96Smrg
20215dfecf96Smrg
20225dfecf96Smrg/************************************************************************
20235dfecf96Smrg * IOR
20245dfecf96Smrg ************************************************************************/
20255dfecf96Smrgstatic void
20265dfecf96Smrgior_real_object(n_real *real, LispObj *obj)
20275dfecf96Smrg{
20285dfecf96Smrg    mpi *bigi, iop;
20295dfecf96Smrg
20305dfecf96Smrg    switch (OBJECT_TYPE(obj)) {
20315dfecf96Smrg	case LispFixnum_t:
20325dfecf96Smrg	    switch (RTYPE(real)) {
20335dfecf96Smrg		case N_FIXNUM:
20345dfecf96Smrg		    RFI(real) |= OFI(obj);
20355dfecf96Smrg		    break;
20365dfecf96Smrg		case N_BIGNUM:
20375dfecf96Smrg		    mpi_init(&iop);
20385dfecf96Smrg		    mpi_seti(&iop, OFI(obj));
20395dfecf96Smrg		    mpi_ior(RBI(real), RBI(real), &iop);
20405dfecf96Smrg		    mpi_clear(&iop);
20415dfecf96Smrg		    rbi_canonicalize(real);
20425dfecf96Smrg		    break;
20435dfecf96Smrg	    }
20445dfecf96Smrg	    break;
20455dfecf96Smrg	case LispInteger_t:
20465dfecf96Smrg	    switch (RTYPE(real)) {
20475dfecf96Smrg		case N_FIXNUM:
20485dfecf96Smrg		    RFI(real) |= OII(obj);
20495dfecf96Smrg		    break;
20505dfecf96Smrg		case N_BIGNUM:
20515dfecf96Smrg		    mpi_init(&iop);
20525dfecf96Smrg		    mpi_seti(&iop, OII(obj));
20535dfecf96Smrg		    mpi_ior(RBI(real), RBI(real), &iop);
20545dfecf96Smrg		    mpi_clear(&iop);
20555dfecf96Smrg		    rbi_canonicalize(real);
20565dfecf96Smrg		    break;
20575dfecf96Smrg	    }
20585dfecf96Smrg	    break;
20595dfecf96Smrg	case LispBignum_t:
20605dfecf96Smrg	    switch (RTYPE(real)) {
20615dfecf96Smrg		case N_FIXNUM:
20625dfecf96Smrg		    bigi = XALLOC(mpi);
20635dfecf96Smrg		    mpi_init(bigi);
20645dfecf96Smrg		    mpi_seti(bigi, RFI(real));
20655dfecf96Smrg		    mpi_ior(bigi, bigi, OBI(obj));
20665dfecf96Smrg		    RTYPE(real) = N_BIGNUM;
20675dfecf96Smrg		    RBI(real) = bigi;
20685dfecf96Smrg		    rbi_canonicalize(real);
20695dfecf96Smrg		    break;
20705dfecf96Smrg		case N_BIGNUM:
20715dfecf96Smrg		    mpi_ior(RBI(real), RBI(real), OBI(obj));
20725dfecf96Smrg		    rbi_canonicalize(real);
20735dfecf96Smrg		    break;
20745dfecf96Smrg	    }
20755dfecf96Smrg	    break;
20765dfecf96Smrg	default:
20775dfecf96Smrg	    fatal_object_error(obj, NOT_AN_INTEGER);
20785dfecf96Smrg	    break;
20795dfecf96Smrg    }
20805dfecf96Smrg}
20815dfecf96Smrg
20825dfecf96Smrg
20835dfecf96Smrg/************************************************************************
20845dfecf96Smrg * NOT
20855dfecf96Smrg ************************************************************************/
20865dfecf96Smrgstatic void
20875dfecf96Smrgnot_real(n_real *real)
20885dfecf96Smrg{
20895dfecf96Smrg    if (RTYPE(real) == N_FIXNUM)
20905dfecf96Smrg	RFI(real) = ~RFI(real);
20915dfecf96Smrg    else {
20925dfecf96Smrg	mpi_com(RBI(real), RBI(real));
20935dfecf96Smrg	rbi_canonicalize(real);
20945dfecf96Smrg    }
20955dfecf96Smrg}
20965dfecf96Smrg
20975dfecf96Smrg/************************************************************************
20985dfecf96Smrg * XOR
20995dfecf96Smrg ************************************************************************/
21005dfecf96Smrgstatic void
21015dfecf96Smrgxor_real_object(n_real *real, LispObj *obj)
21025dfecf96Smrg{
21035dfecf96Smrg    mpi *bigi, iop;
21045dfecf96Smrg
21055dfecf96Smrg    switch (OBJECT_TYPE(obj)) {
21065dfecf96Smrg	case LispFixnum_t:
21075dfecf96Smrg	    switch (RTYPE(real)) {
21085dfecf96Smrg		case N_FIXNUM:
21095dfecf96Smrg		    RFI(real) ^= OFI(obj);
21105dfecf96Smrg		    break;
21115dfecf96Smrg		case N_BIGNUM:
21125dfecf96Smrg		    mpi_init(&iop);
21135dfecf96Smrg		    mpi_seti(&iop, OFI(obj));
21145dfecf96Smrg		    mpi_xor(RBI(real), RBI(real), &iop);
21155dfecf96Smrg		    mpi_clear(&iop);
21165dfecf96Smrg		    rbi_canonicalize(real);
21175dfecf96Smrg		    break;
21185dfecf96Smrg	    }
21195dfecf96Smrg	    break;
21205dfecf96Smrg	case LispInteger_t:
21215dfecf96Smrg	    switch (RTYPE(real)) {
21225dfecf96Smrg		case N_FIXNUM:
21235dfecf96Smrg		    RFI(real) ^= OII(obj);
21245dfecf96Smrg		    break;
21255dfecf96Smrg		case N_BIGNUM:
21265dfecf96Smrg		    mpi_init(&iop);
21275dfecf96Smrg		    mpi_seti(&iop, OII(obj));
21285dfecf96Smrg		    mpi_xor(RBI(real), RBI(real), &iop);
21295dfecf96Smrg		    mpi_clear(&iop);
21305dfecf96Smrg		    rbi_canonicalize(real);
21315dfecf96Smrg		    break;
21325dfecf96Smrg	    }
21335dfecf96Smrg	    break;
21345dfecf96Smrg	case LispBignum_t:
21355dfecf96Smrg	    switch (RTYPE(real)) {
21365dfecf96Smrg		case N_FIXNUM:
21375dfecf96Smrg		    bigi = XALLOC(mpi);
21385dfecf96Smrg		    mpi_init(bigi);
21395dfecf96Smrg		    mpi_seti(bigi, RFI(real));
21405dfecf96Smrg		    mpi_xor(bigi, bigi, OBI(obj));
21415dfecf96Smrg		    RTYPE(real) = N_BIGNUM;
21425dfecf96Smrg		    RBI(real) = bigi;
21435dfecf96Smrg		    rbi_canonicalize(real);
21445dfecf96Smrg		    break;
21455dfecf96Smrg		case N_BIGNUM:
21465dfecf96Smrg		    mpi_xor(RBI(real), RBI(real), OBI(obj));
21475dfecf96Smrg		    rbi_canonicalize(real);
21485dfecf96Smrg		    break;
21495dfecf96Smrg	    }
21505dfecf96Smrg	    break;
21515dfecf96Smrg	default:
21525dfecf96Smrg	    fatal_object_error(obj, NOT_AN_INTEGER);
21535dfecf96Smrg	    break;
21545dfecf96Smrg    }
21555dfecf96Smrg}
21565dfecf96Smrg
21575dfecf96Smrg
21585dfecf96Smrg/************************************************************************
21595dfecf96Smrg * DIVIDE
21605dfecf96Smrg ************************************************************************/
21615dfecf96Smrgstatic void
21625dfecf96Smrgdivide_number_object(n_number *num, LispObj *obj, int fun, int flo)
21635dfecf96Smrg{
21645dfecf96Smrg    switch (OBJECT_TYPE(obj)) {
21655dfecf96Smrg	case LispFixnum_t:
21665dfecf96Smrg	    switch (NRTYPE(num)) {
21675dfecf96Smrg		case N_FIXNUM:
21685dfecf96Smrg		    ndivide_fi_fi(num, OFI(obj), fun, flo);
21695dfecf96Smrg		    break;
21705dfecf96Smrg		case N_BIGNUM:
21715dfecf96Smrg		    ndivide_xi_xi(num, obj, fun, flo);
21725dfecf96Smrg		    break;
21735dfecf96Smrg		case N_FLONUM:
21745dfecf96Smrg		    ndivide_flonum(num, NRFF(num), (double)OFI(obj), fun, flo);
21755dfecf96Smrg		    break;
21765dfecf96Smrg		case N_FIXRATIO:
21775dfecf96Smrg		case N_BIGRATIO:
21785dfecf96Smrg		    ndivide_xr_xi(num, obj, fun, flo);
21795dfecf96Smrg		    break;
21805dfecf96Smrg	    }
21815dfecf96Smrg	    break;
21825dfecf96Smrg	case LispInteger_t:
21835dfecf96Smrg	    switch (NRTYPE(num)) {
21845dfecf96Smrg		case N_FIXNUM:
21855dfecf96Smrg		    ndivide_fi_fi(num, OII(obj), fun, flo);
21865dfecf96Smrg		    break;
21875dfecf96Smrg		case N_BIGNUM:
21885dfecf96Smrg		    ndivide_xi_xi(num, obj, fun, flo);
21895dfecf96Smrg		    break;
21905dfecf96Smrg		case N_FLONUM:
21915dfecf96Smrg		    ndivide_flonum(num, NRFF(num), (double)OII(obj), fun, flo);
21925dfecf96Smrg		    break;
21935dfecf96Smrg		case N_FIXRATIO:
21945dfecf96Smrg		case N_BIGRATIO:
21955dfecf96Smrg		    ndivide_xr_xi(num, obj, fun, flo);
21965dfecf96Smrg		    break;
21975dfecf96Smrg	    }
21985dfecf96Smrg	    break;
21995dfecf96Smrg	case LispBignum_t:
22005dfecf96Smrg	    switch (NRTYPE(num)) {
22015dfecf96Smrg		case N_FIXNUM:
22025dfecf96Smrg		case N_BIGNUM:
22035dfecf96Smrg		    ndivide_xi_xi(num, obj, fun, flo);
22045dfecf96Smrg		    break;
22055dfecf96Smrg		case N_FLONUM:
22065dfecf96Smrg		    ndivide_flonum(num, NRFF(num), bi_getd(OBI(obj)),
22075dfecf96Smrg				   fun, flo);
22085dfecf96Smrg		    break;
22095dfecf96Smrg		case N_FIXRATIO:
22105dfecf96Smrg		case N_BIGRATIO:
22115dfecf96Smrg		    ndivide_xr_xi(num, obj, fun, flo);
22125dfecf96Smrg		    break;
22135dfecf96Smrg	    }
22145dfecf96Smrg	    break;
22155dfecf96Smrg	case LispDFloat_t:
22165dfecf96Smrg	    switch (NRTYPE(num)) {
22175dfecf96Smrg		case N_FIXNUM:
22185dfecf96Smrg		    ndivide_flonum(num, (double)NRFI(num), ODF(obj),
22195dfecf96Smrg				   fun, flo);
22205dfecf96Smrg		    break;
22215dfecf96Smrg		case N_BIGNUM:
22225dfecf96Smrg		    ndivide_flonum(num, bi_getd(NRBI(num)), ODF(obj),
22235dfecf96Smrg				   fun, flo);
22245dfecf96Smrg		    break;
22255dfecf96Smrg		case N_FLONUM:
22265dfecf96Smrg		    ndivide_flonum(num, NRFF(num), ODF(obj), fun, flo);
22275dfecf96Smrg		    break;
22285dfecf96Smrg		case N_FIXRATIO:
22295dfecf96Smrg		    ndivide_flonum(num,
22305dfecf96Smrg				   (double)NRFRN(num) / (double)NRFRD(num),
22315dfecf96Smrg				   ODF(obj), fun, flo);
22325dfecf96Smrg		    break;
22335dfecf96Smrg		case N_BIGRATIO:
22345dfecf96Smrg		    ndivide_flonum(num, br_getd(NRBR(num)), ODF(obj),
22355dfecf96Smrg				   fun, flo);
22365dfecf96Smrg		    break;
22375dfecf96Smrg	    }
22385dfecf96Smrg	    break;
22395dfecf96Smrg	case LispRatio_t:
22405dfecf96Smrg	    switch (NRTYPE(num)) {
22415dfecf96Smrg		case N_FIXNUM:
22425dfecf96Smrg		case N_BIGNUM:
22435dfecf96Smrg		    ndivide_xi_xr(num, obj, fun, flo);
22445dfecf96Smrg		    break;
22455dfecf96Smrg		case N_FLONUM:
22465dfecf96Smrg		    ndivide_flonum(num, NRFF(num),
22475dfecf96Smrg				   (double)OFRN(obj) / (double)OFRD(obj),
22485dfecf96Smrg				   fun, flo);
22495dfecf96Smrg		    break;
22505dfecf96Smrg		case N_FIXRATIO:
22515dfecf96Smrg		case N_BIGRATIO:
22525dfecf96Smrg		    ndivide_xr_xr(num, obj, fun, flo);
22535dfecf96Smrg		    break;
22545dfecf96Smrg	    }
22555dfecf96Smrg	    break;
22565dfecf96Smrg	case LispBigratio_t:
22575dfecf96Smrg	    switch (NRTYPE(num)) {
22585dfecf96Smrg		case N_FIXNUM:
22595dfecf96Smrg		case N_BIGNUM:
22605dfecf96Smrg		    ndivide_xi_xr(num, obj, fun, flo);
22615dfecf96Smrg		    break;
22625dfecf96Smrg		case N_FLONUM:
22635dfecf96Smrg		    ndivide_flonum(num, NRFF(num), br_getd(OBR(obj)),
22645dfecf96Smrg				   fun, flo);
22655dfecf96Smrg		    break;
22665dfecf96Smrg		case N_FIXRATIO:
22675dfecf96Smrg		case N_BIGRATIO:
22685dfecf96Smrg		    ndivide_xr_xr(num, obj, fun, flo);
22695dfecf96Smrg		    break;
22705dfecf96Smrg	    }
22715dfecf96Smrg	    break;
22725dfecf96Smrg	default:
22735dfecf96Smrg	    fatal_object_error(obj, NOT_A_REAL_NUMBER);
22745dfecf96Smrg	    break;
22755dfecf96Smrg    }
22765dfecf96Smrg}
22775dfecf96Smrg
22785dfecf96Smrg
22795dfecf96Smrg/************************************************************************
22805dfecf96Smrg * COMPARE
22815dfecf96Smrg ************************************************************************/
22825dfecf96Smrgstatic int
22835dfecf96Smrgcmp_real_real(n_real *op1, n_real *op2)
22845dfecf96Smrg{
22855dfecf96Smrg    switch (RTYPE(op1)) {
22865dfecf96Smrg	case N_FIXNUM:
22875dfecf96Smrg	    switch (RTYPE(op2)) {
22885dfecf96Smrg		case N_FIXNUM:
22895dfecf96Smrg		    return (cmp_fi_fi(RFI(op1), RFI(op2)));
22905dfecf96Smrg		case N_BIGNUM:
22915dfecf96Smrg		    return (cmp_fi_bi(RFI(op1), RBI(op2)));
22925dfecf96Smrg		case N_FLONUM:
22935dfecf96Smrg		    return (cmp_flonum((double)RFI(op1), RFF(op2)));
22945dfecf96Smrg		case N_FIXRATIO:
22955dfecf96Smrg		    return (cmp_fi_fr(RFI(op1), RFRN(op2), RFRD(op2)));
22965dfecf96Smrg		case N_BIGRATIO:
22975dfecf96Smrg		    return (cmp_fi_br(RFI(op1), RBR(op2)));
22985dfecf96Smrg	    }
22995dfecf96Smrg	    break;
23005dfecf96Smrg	case N_BIGNUM:
23015dfecf96Smrg	    switch (RTYPE(op2)) {
23025dfecf96Smrg		case N_FIXNUM:
23035dfecf96Smrg		    return (cmp_bi_fi(RBI(op1), RFI(op2)));
23045dfecf96Smrg		case N_BIGNUM:
23055dfecf96Smrg		    return (cmp_bi_bi(RBI(op1), RBI(op2)));
23065dfecf96Smrg		case N_FLONUM:
23075dfecf96Smrg		    return (cmp_flonum(bi_getd(RBI(op1)), RFF(op2)));
23085dfecf96Smrg		case N_FIXRATIO:
23095dfecf96Smrg		    return (cmp_bi_fr(RBI(op1), RFRN(op2), RFRD(op2)));
23105dfecf96Smrg		case N_BIGRATIO:
23115dfecf96Smrg		    return (cmp_bi_br(RBI(op1), RBR(op2)));
23125dfecf96Smrg	    }
23135dfecf96Smrg	    break;
23145dfecf96Smrg	case N_FLONUM:
23155dfecf96Smrg	    switch (RTYPE(op2)) {
23165dfecf96Smrg		case N_FIXNUM:
23175dfecf96Smrg		    return (cmp_flonum(RFF(op1), (double)RFI(op2)));
23185dfecf96Smrg		case N_BIGNUM:
23195dfecf96Smrg		    return (cmp_flonum(RFF(op1), bi_getd(RBI(op2))));
23205dfecf96Smrg		case N_FLONUM:
23215dfecf96Smrg		    return (cmp_flonum(RFF(op1), RFF(op2)));
23225dfecf96Smrg		case N_FIXRATIO:
23235dfecf96Smrg		    return (cmp_flonum(RFF(op1),
23245dfecf96Smrg				       (double)RFRN(op2) / (double)RFRD(op2)));
23255dfecf96Smrg		case N_BIGRATIO:
23265dfecf96Smrg		    return (cmp_flonum(RFF(op1), br_getd(RBR(op2))));
23275dfecf96Smrg	    }
23285dfecf96Smrg	    break;
23295dfecf96Smrg	case N_FIXRATIO:
23305dfecf96Smrg	    switch (RTYPE(op2)) {
23315dfecf96Smrg		case N_FIXNUM:
23325dfecf96Smrg		    return (cmp_fr_fi(RFRN(op1), RFRD(op1), RFI(op2)));
23335dfecf96Smrg		case N_BIGNUM:
23345dfecf96Smrg		    return (cmp_fr_bi(RFRN(op1), RFRD(op1), RBI(op2)));
23355dfecf96Smrg		case N_FLONUM:
23365dfecf96Smrg		    return (cmp_flonum((double)RFRN(op1) / (double)RFRD(op1),
23375dfecf96Smrg				       RFF(op2)));
23385dfecf96Smrg		case N_FIXRATIO:
23395dfecf96Smrg		    return (cmp_fr_fr(RFRN(op1), RFRD(op1),
23405dfecf96Smrg				      RFRN(op2), RFRD(op2)));
23415dfecf96Smrg		case N_BIGRATIO:
23425dfecf96Smrg		    return (cmp_fr_br(RFRN(op1), RFRD(op1), RBR(op2)));
23435dfecf96Smrg	    }
23445dfecf96Smrg	    break;
23455dfecf96Smrg	case N_BIGRATIO:
23465dfecf96Smrg	    switch (RTYPE(op2)) {
23475dfecf96Smrg		case N_FIXNUM:
23485dfecf96Smrg		    return (cmp_br_fi(RBR(op1), RFI(op2)));
23495dfecf96Smrg		case N_BIGNUM:
23505dfecf96Smrg		    return (cmp_br_bi(RBR(op1), RBI(op2)));
23515dfecf96Smrg		case N_FLONUM:
23525dfecf96Smrg		    return (cmp_flonum(br_getd(RBR(op1)), RFF(op2)));
23535dfecf96Smrg		case N_FIXRATIO:
23545dfecf96Smrg		    return (cmp_br_fr(RBR(op1), RFRN(op2), RFRD(op2)));
23555dfecf96Smrg		case N_BIGRATIO:
23565dfecf96Smrg		    return (cmp_br_br(RBR(op1), RBR(op2)));
23575dfecf96Smrg	    }
23585dfecf96Smrg    }
23595dfecf96Smrg
23605dfecf96Smrg    return (0);
23615dfecf96Smrg}
23625dfecf96Smrg
23635dfecf96Smrgstatic int
23645dfecf96Smrgcmp_real_object(n_real *op1, LispObj *op2)
23655dfecf96Smrg{
23665dfecf96Smrg    switch (OBJECT_TYPE(op2)) {
23675dfecf96Smrg	case LispFixnum_t:
23685dfecf96Smrg	    switch (RTYPE(op1)) {
23695dfecf96Smrg		case N_FIXNUM:
23705dfecf96Smrg		    return (cmp_fi_fi(RFI(op1), OFI(op2)));
23715dfecf96Smrg		case N_BIGNUM:
23725dfecf96Smrg		    return (cmp_bi_fi(RBI(op1), OFI(op2)));
23735dfecf96Smrg		case N_FLONUM:
23745dfecf96Smrg		    return (cmp_flonum(RFF(op1), (double)OFI(op2)));
23755dfecf96Smrg		case N_FIXRATIO:
23765dfecf96Smrg		    return (cmp_fr_fi(RFRD(op1), RFRN(op1), OFI(op2)));
23775dfecf96Smrg		case N_BIGRATIO:
23785dfecf96Smrg		    return (cmp_br_fi(RBR(op1), OFI(op2)));
23795dfecf96Smrg	    }
23805dfecf96Smrg	    break;
23815dfecf96Smrg	case LispInteger_t:
23825dfecf96Smrg	    switch (RTYPE(op1)) {
23835dfecf96Smrg		case N_FIXNUM:
23845dfecf96Smrg		    return (cmp_fi_fi(RFI(op1), OII(op2)));
23855dfecf96Smrg		case N_BIGNUM:
23865dfecf96Smrg		    return (cmp_bi_fi(RBI(op1), OII(op2)));
23875dfecf96Smrg		case N_FLONUM:
23885dfecf96Smrg		    return (cmp_flonum(RFF(op1), (double)OII(op2)));
23895dfecf96Smrg		case N_FIXRATIO:
23905dfecf96Smrg		    return (cmp_fr_fi(RFRD(op1), RFRN(op1), OII(op2)));
23915dfecf96Smrg		case N_BIGRATIO:
23925dfecf96Smrg		    return (cmp_br_fi(RBR(op1), OII(op2)));
23935dfecf96Smrg	    }
23945dfecf96Smrg	    break;
23955dfecf96Smrg	case LispBignum_t:
23965dfecf96Smrg	    switch (RTYPE(op1)) {
23975dfecf96Smrg		case N_FIXNUM:
23985dfecf96Smrg		    return (cmp_fi_bi(RFI(op1), OBI(op2)));
23995dfecf96Smrg		case N_BIGNUM:
24005dfecf96Smrg		    return (cmp_bi_bi(RBI(op1), OBI(op2)));
24015dfecf96Smrg		case N_FLONUM:
24025dfecf96Smrg		    return (cmp_flonum(RFF(op1), bi_getd(OBI(op2))));
24035dfecf96Smrg		case N_FIXRATIO:
24045dfecf96Smrg		    return (cmp_fr_bi(RFRD(op1), RFRN(op1), OBI(op2)));
24055dfecf96Smrg		case N_BIGRATIO:
24065dfecf96Smrg		    return (cmp_br_bi(RBR(op1), OBI(op2)));
24075dfecf96Smrg	    }
24085dfecf96Smrg	    break;
24095dfecf96Smrg	case LispDFloat_t:
24105dfecf96Smrg	    switch (RTYPE(op1)) {
24115dfecf96Smrg		case N_FIXNUM:
24125dfecf96Smrg		    return (cmp_flonum((double)RFI(op1), ODF(op2)));
24135dfecf96Smrg		case N_BIGNUM:
24145dfecf96Smrg		    return (cmp_flonum(bi_getd(RBI(op1)), ODF(op2)));
24155dfecf96Smrg		case N_FLONUM:
24165dfecf96Smrg		    return (cmp_flonum(RFF(op1), ODF(op2)));
24175dfecf96Smrg		case N_FIXRATIO:
24185dfecf96Smrg		    return (cmp_flonum((double)RFRN(op1) / (double)RFRD(op1),
24195dfecf96Smrg				       ODF(op2)));
24205dfecf96Smrg		case N_BIGRATIO:
24215dfecf96Smrg		    return (cmp_flonum(br_getd(RBR(op1)), ODF(op2)));
24225dfecf96Smrg	    }
24235dfecf96Smrg	    break;
24245dfecf96Smrg	case LispRatio_t:
24255dfecf96Smrg	    switch (RTYPE(op1)) {
24265dfecf96Smrg		case N_FIXNUM:
24275dfecf96Smrg		    return (cmp_fi_fr(RFI(op1), OFRN(op2), OFRD(op2)));
24285dfecf96Smrg		case N_BIGNUM:
24295dfecf96Smrg		    return (cmp_bi_fr(RBI(op1), OFRN(op2), OFRD(op2)));
24305dfecf96Smrg		case N_FLONUM:
24315dfecf96Smrg		    return (cmp_flonum(RFF(op1),
24325dfecf96Smrg				       (double)OFRN(op2) / (double)OFRD(op2)));
24335dfecf96Smrg		case N_FIXRATIO:
24345dfecf96Smrg		    return (cmp_fr_fr(RFRN(op1), RFRD(op1),
24355dfecf96Smrg				      OFRN(op2), OFRD(op2)));
24365dfecf96Smrg		case N_BIGRATIO:
24375dfecf96Smrg		    return (cmp_br_fr(RBR(op1), OFRN(op2), OFRD(op2)));
24385dfecf96Smrg	    }
24395dfecf96Smrg	    break;
24405dfecf96Smrg	case LispBigratio_t:
24415dfecf96Smrg	    switch (RTYPE(op1)) {
24425dfecf96Smrg		case N_FIXNUM:
24435dfecf96Smrg		    return (cmp_fi_br(RFI(op1), OBR(op2)));
24445dfecf96Smrg		case N_BIGNUM:
24455dfecf96Smrg		    return (cmp_bi_br(RBI(op1), OBR(op2)));
24465dfecf96Smrg		case N_FLONUM:
24475dfecf96Smrg		    return (cmp_flonum(RFF(op1), br_getd(OBR(op2))));
24485dfecf96Smrg		case N_FIXRATIO:
24495dfecf96Smrg		    return (cmp_fr_br(RFRN(op1), RFRD(op1), OBR(op2)));
24505dfecf96Smrg		case N_BIGRATIO:
24515dfecf96Smrg		    return (cmp_br_br(RBR(op1), OBR(op2)));
24525dfecf96Smrg	    }
24535dfecf96Smrg	    break;
24545dfecf96Smrg	default:
24555dfecf96Smrg	    fatal_object_error(op2, NOT_A_REAL_NUMBER);
24565dfecf96Smrg	    break;
24575dfecf96Smrg    }
24585dfecf96Smrg
24595dfecf96Smrg    return (0);
24605dfecf96Smrg}
24615dfecf96Smrg
24625dfecf96Smrg#if 0		/* not used */
24635dfecf96Smrgstatic int
24645dfecf96Smrgcmp_number_object(n_number *op1, LispObj *op2)
24655dfecf96Smrg{
24665dfecf96Smrg    if (op1->complex) {
24675dfecf96Smrg	if (OBJECT_TYPE(op2) == LispComplex_t) {
24685dfecf96Smrg	    if (cmp_real_object(NREAL(op1), OCXR(op2)) == 0)
24695dfecf96Smrg		return (cmp_real_object(NIMAG(op1), OCXI(op2)));
24705dfecf96Smrg	    return (1);
24715dfecf96Smrg	}
24725dfecf96Smrg	else if (cmp_real_real(NIMAG(op1), &zero) == 0)
24735dfecf96Smrg	    return (cmp_real_object(NREAL(op1), op2));
24745dfecf96Smrg	else
24755dfecf96Smrg	    return (1);
24765dfecf96Smrg    }
24775dfecf96Smrg    else {
24785dfecf96Smrg	switch (OBJECT_TYPE(op2)) {
24795dfecf96Smrg	    case LispFixnum_t:
24805dfecf96Smrg		switch (NRTYPE(op1)) {
24815dfecf96Smrg		    case N_FIXNUM:
24825dfecf96Smrg			return (cmp_fi_fi(NRFI(op1), OFI(op2)));
24835dfecf96Smrg		    case N_BIGNUM:
24845dfecf96Smrg			return (cmp_bi_fi(NRBI(op1), OFI(op2)));
24855dfecf96Smrg		    case N_FLONUM:
24865dfecf96Smrg			return (cmp_flonum(NRFF(op1), (double)OFI(op2)));
24875dfecf96Smrg		    case N_FIXRATIO:
24885dfecf96Smrg			return (cmp_fr_fi(NRFRD(op1), NRFRN(op1), OFI(op2)));
24895dfecf96Smrg		    case N_BIGRATIO:
24905dfecf96Smrg			return (cmp_br_fi(NRBR(op1), OFI(op2)));
24915dfecf96Smrg		}
24925dfecf96Smrg		break;
24935dfecf96Smrg	    case LispInteger_t:
24945dfecf96Smrg		switch (NRTYPE(op1)) {
24955dfecf96Smrg		    case N_FIXNUM:
24965dfecf96Smrg			return (cmp_fi_fi(NRFI(op1), OII(op2)));
24975dfecf96Smrg		    case N_BIGNUM:
24985dfecf96Smrg			return (cmp_bi_fi(NRBI(op1), OII(op2)));
24995dfecf96Smrg		    case N_FLONUM:
25005dfecf96Smrg			return (cmp_flonum(NRFF(op1), (double)OII(op2)));
25015dfecf96Smrg		    case N_FIXRATIO:
25025dfecf96Smrg			return (cmp_fr_fi(NRFRD(op1), NRFRN(op1), OII(op2)));
25035dfecf96Smrg		    case N_BIGRATIO:
25045dfecf96Smrg			return (cmp_br_fi(NRBR(op1), OII(op2)));
25055dfecf96Smrg		}
25065dfecf96Smrg		break;
25075dfecf96Smrg	    case LispBignum_t:
25085dfecf96Smrg		switch (NRTYPE(op1)) {
25095dfecf96Smrg		    case N_FIXNUM:
25105dfecf96Smrg			return (cmp_fi_bi(NRFI(op1), OBI(op2)));
25115dfecf96Smrg		    case N_BIGNUM:
25125dfecf96Smrg			return (cmp_bi_bi(NRBI(op1), OBI(op2)));
25135dfecf96Smrg		    case N_FLONUM:
25145dfecf96Smrg			return (cmp_flonum(NRFF(op1), bi_getd(OBI(op2))));
25155dfecf96Smrg		    case N_FIXRATIO:
25165dfecf96Smrg			return (cmp_fr_bi(NRFRD(op1), NRFRN(op1), OBI(op2)));
25175dfecf96Smrg		    case N_BIGRATIO:
25185dfecf96Smrg			return (cmp_br_bi(NRBR(op1), OBI(op2)));
25195dfecf96Smrg		}
25205dfecf96Smrg		break;
25215dfecf96Smrg	    case LispDFloat_t:
25225dfecf96Smrg		switch (NRTYPE(op1)) {
25235dfecf96Smrg		    case N_FIXNUM:
25245dfecf96Smrg			return (cmp_flonum((double)NRFI(op1), ODF(op2)));
25255dfecf96Smrg		    case N_BIGNUM:
25265dfecf96Smrg			return (cmp_flonum(bi_getd(NRBI(op1)), ODF(op2)));
25275dfecf96Smrg		    case N_FLONUM:
25285dfecf96Smrg			return (cmp_flonum(NRFF(op1), ODF(op2)));
25295dfecf96Smrg		    case N_FIXRATIO:
25305dfecf96Smrg			return (cmp_flonum((double)NRFRN(op1) /
25315dfecf96Smrg					   (double)NRFRD(op1),
25325dfecf96Smrg					   ODF(op2)));
25335dfecf96Smrg		    case N_BIGRATIO:
25345dfecf96Smrg			return (cmp_flonum(br_getd(NRBR(op1)), ODF(op2)));
25355dfecf96Smrg		}
25365dfecf96Smrg		break;
25375dfecf96Smrg	    case LispRatio_t:
25385dfecf96Smrg		switch (NRTYPE(op1)) {
25395dfecf96Smrg		    case N_FIXNUM:
25405dfecf96Smrg			return (cmp_fi_fr(NRFI(op1), OFRN(op2), OFRD(op2)));
25415dfecf96Smrg		    case N_BIGNUM:
25425dfecf96Smrg			return (cmp_bi_fr(NRBI(op1), OFRN(op2), OFRD(op2)));
25435dfecf96Smrg		    case N_FLONUM:
25445dfecf96Smrg			return (cmp_flonum(NRFF(op1),
25455dfecf96Smrg					   (double)OFRN(op2) / (double)OFRD(op2)));
25465dfecf96Smrg		    case N_FIXRATIO:
25475dfecf96Smrg			return (cmp_fr_fr(NRFRN(op1), NRFRD(op1),
25485dfecf96Smrg					  OFRN(op2), OFRD(op2)));
25495dfecf96Smrg		    case N_BIGRATIO:
25505dfecf96Smrg			return (cmp_br_fr(NRBR(op1), OFRN(op2), OFRD(op2)));
25515dfecf96Smrg		}
25525dfecf96Smrg		break;
25535dfecf96Smrg	    case LispBigratio_t:
25545dfecf96Smrg		switch (NRTYPE(op1)) {
25555dfecf96Smrg		    case N_FIXNUM:
25565dfecf96Smrg			return (cmp_fi_br(NRFI(op1), OBR(op2)));
25575dfecf96Smrg		    case N_BIGNUM:
25585dfecf96Smrg			return (cmp_bi_br(NRBI(op1), OBR(op2)));
25595dfecf96Smrg		    case N_FLONUM:
25605dfecf96Smrg			return (cmp_flonum(NRFF(op1), br_getd(OBR(op2))));
25615dfecf96Smrg		    case N_FIXRATIO:
25625dfecf96Smrg			return (cmp_fr_br(NRFRN(op1), NRFRD(op1), OBR(op2)));
25635dfecf96Smrg		    case N_BIGRATIO:
25645dfecf96Smrg			return (cmp_br_br(NRBR(op1), OBR(op2)));
25655dfecf96Smrg		}
25665dfecf96Smrg		break;
25675dfecf96Smrg	    case LispComplex_t:
25685dfecf96Smrg		if (cmp_real_object(&zero, OCXI(op2)) == 0)
25695dfecf96Smrg		    return (cmp_real_object(NREAL(op1), OCXR(op2)));
25705dfecf96Smrg		return (1);
25715dfecf96Smrg	    default:
25725dfecf96Smrg		fatal_object_error(op2, NOT_A_NUMBER);
25735dfecf96Smrg		break;
25745dfecf96Smrg	}
25755dfecf96Smrg    }
25765dfecf96Smrg
25775dfecf96Smrg    return (0);
25785dfecf96Smrg}
25795dfecf96Smrg#endif
25805dfecf96Smrg
25815dfecf96Smrgstatic int
25825dfecf96Smrgcmp_object_object(LispObj *op1, LispObj *op2, int real)
25835dfecf96Smrg{
25845dfecf96Smrg    if (OBJECT_TYPE(op1) == LispComplex_t) {
25855dfecf96Smrg	if (real)
25865dfecf96Smrg	    fatal_object_error(op1, NOT_A_REAL_NUMBER);
25875dfecf96Smrg	if (OBJECT_TYPE(op2) == LispComplex_t)
25885dfecf96Smrg	    return (cmp_cx_cx(op1, op2));
25895dfecf96Smrg	else if (cmp_real_object(&zero, OCXI(op1)) == 0)
25905dfecf96Smrg	    return (cmp_object_object(OCXR(op1), op2, real));
25915dfecf96Smrg	return (1);
25925dfecf96Smrg    }
25935dfecf96Smrg    else if (OBJECT_TYPE(op2) == LispComplex_t) {
25945dfecf96Smrg	if (real)
25955dfecf96Smrg	    fatal_object_error(op1, NOT_A_REAL_NUMBER);
25965dfecf96Smrg	if (cmp_real_object(&zero, OCXI(op2)) == 0)
25975dfecf96Smrg	    return (cmp_object_object(op1, OCXR(op2), real));
25985dfecf96Smrg	return (1);
25995dfecf96Smrg    }
26005dfecf96Smrg    else {
26015dfecf96Smrg	switch (OBJECT_TYPE(op1)) {
26025dfecf96Smrg	    case LispFixnum_t:
26035dfecf96Smrg		switch (OBJECT_TYPE(op2)) {
26045dfecf96Smrg		    case LispFixnum_t:
26055dfecf96Smrg			return (cmp_fi_fi(OFI(op1), OFI(op2)));
26065dfecf96Smrg		    case LispInteger_t:
26075dfecf96Smrg			return (cmp_fi_fi(OFI(op1), OII(op2)));
26085dfecf96Smrg		    case LispBignum_t:
26095dfecf96Smrg			return (cmp_fi_bi(OFI(op1), OBI(op2)));
26105dfecf96Smrg		    case LispDFloat_t:
26115dfecf96Smrg			return (cmp_flonum((double)OFI(op1), ODF(op2)));
26125dfecf96Smrg		    case LispRatio_t:
26135dfecf96Smrg			return (cmp_fi_fr(OFI(op1),
26145dfecf96Smrg					  OFRN(op2), OFRD(op2)));
26155dfecf96Smrg		    case LispBigratio_t:
26165dfecf96Smrg			return (cmp_fi_br(OFI(op1), OBR(op2)));
26175dfecf96Smrg		    default:
26185dfecf96Smrg			break;
26195dfecf96Smrg		}
26205dfecf96Smrg		break;
26215dfecf96Smrg	    case LispInteger_t:
26225dfecf96Smrg		switch (OBJECT_TYPE(op2)) {
26235dfecf96Smrg		    case LispFixnum_t:
26245dfecf96Smrg			return (cmp_fi_fi(OII(op1), OFI(op2)));
26255dfecf96Smrg		    case LispInteger_t:
26265dfecf96Smrg			return (cmp_fi_fi(OII(op1), OII(op2)));
26275dfecf96Smrg		    case LispBignum_t:
26285dfecf96Smrg			return (cmp_fi_bi(OII(op1), OBI(op2)));
26295dfecf96Smrg		    case LispDFloat_t:
26305dfecf96Smrg			return (cmp_flonum((double)OII(op1), ODF(op2)));
26315dfecf96Smrg		    case LispRatio_t:
26325dfecf96Smrg			return (cmp_fi_fr(OII(op1),
26335dfecf96Smrg					  OFRN(op2), OFRD(op2)));
26345dfecf96Smrg		    case LispBigratio_t:
26355dfecf96Smrg			return (cmp_fi_br(OII(op1), OBR(op2)));
26365dfecf96Smrg		    default:
26375dfecf96Smrg			break;
26385dfecf96Smrg		}
26395dfecf96Smrg		break;
26405dfecf96Smrg	    case LispBignum_t:
26415dfecf96Smrg		switch (OBJECT_TYPE(op2)) {
26425dfecf96Smrg		    case LispFixnum_t:
26435dfecf96Smrg			return (cmp_bi_fi(OBI(op1), OFI(op2)));
26445dfecf96Smrg		    case LispInteger_t:
26455dfecf96Smrg			return (cmp_bi_fi(OBI(op1), OII(op2)));
26465dfecf96Smrg		    case LispBignum_t:
26475dfecf96Smrg			return (cmp_bi_bi(OBI(op1), OBI(op2)));
26485dfecf96Smrg		    case LispDFloat_t:
26495dfecf96Smrg			return (cmp_flonum(bi_getd(OBI(op1)), ODF(op2)));
26505dfecf96Smrg		    case LispRatio_t:
26515dfecf96Smrg			return (cmp_bi_fr(OBI(op1),
26525dfecf96Smrg					  OFRN(op2), OFRD(op2)));
26535dfecf96Smrg		    case LispBigratio_t:
26545dfecf96Smrg			return (cmp_bi_br(OBI(op1), OBR(op2)));
26555dfecf96Smrg		    default:
26565dfecf96Smrg			break;
26575dfecf96Smrg		}
26585dfecf96Smrg		break;
26595dfecf96Smrg	    case LispDFloat_t:
26605dfecf96Smrg		switch (OBJECT_TYPE(op2)) {
26615dfecf96Smrg		    case LispFixnum_t:
26625dfecf96Smrg			return (cmp_flonum(ODF(op1), (double)OFI(op2)));
26635dfecf96Smrg		    case LispInteger_t:
26645dfecf96Smrg			return (cmp_flonum(ODF(op1), (double)OII(op2)));
26655dfecf96Smrg		    case LispBignum_t:
26665dfecf96Smrg			return (cmp_flonum(ODF(op1), bi_getd(OBI(op2))));
26675dfecf96Smrg		    case LispDFloat_t:
26685dfecf96Smrg			return (cmp_flonum(ODF(op1), ODF(op2)));
26695dfecf96Smrg			break;
26705dfecf96Smrg		    case LispRatio_t:
26715dfecf96Smrg			return (cmp_flonum(ODF(op1),
26725dfecf96Smrg					   (double)OFRN(op2) /
26735dfecf96Smrg					   (double)OFRD(op2)));
26745dfecf96Smrg		    case LispBigratio_t:
26755dfecf96Smrg			return (cmp_flonum(ODF(op1), br_getd(OBR(op2))));
26765dfecf96Smrg		    default:
26775dfecf96Smrg			break;
26785dfecf96Smrg		}
26795dfecf96Smrg		break;
26805dfecf96Smrg	    case LispRatio_t:
26815dfecf96Smrg		switch (OBJECT_TYPE(op2)) {
26825dfecf96Smrg		    case LispFixnum_t:
26835dfecf96Smrg			return (cmp_fr_fi(OFRN(op1), OFRD(op1), OFI(op2)));
26845dfecf96Smrg		    case LispInteger_t:
26855dfecf96Smrg			return (cmp_fr_fi(OFRN(op1), OFRD(op1), OII(op2)));
26865dfecf96Smrg		    case LispBignum_t:
26875dfecf96Smrg			return (cmp_fr_bi(OFRN(op1), OFRD(op1), OBI(op2)));
26885dfecf96Smrg		    case LispDFloat_t:
26895dfecf96Smrg			return (cmp_flonum((double)OFRN(op1) /
26905dfecf96Smrg					   (double)OFRD(op1),
26915dfecf96Smrg					   ODF(op2)));
26925dfecf96Smrg		    case LispRatio_t:
26935dfecf96Smrg			return (cmp_fr_fr(OFRN(op1), OFRD(op1),
26945dfecf96Smrg					  OFRN(op2), OFRD(op2)));
26955dfecf96Smrg		    case LispBigratio_t:
26965dfecf96Smrg			return (cmp_fr_br(OFRN(op1), OFRD(op1), OBR(op2)));
26975dfecf96Smrg		    default:
26985dfecf96Smrg			break;
26995dfecf96Smrg		}
27005dfecf96Smrg		break;
27015dfecf96Smrg	    case LispBigratio_t:
27025dfecf96Smrg		switch (OBJECT_TYPE(op2)) {
27035dfecf96Smrg		    case LispFixnum_t:
27045dfecf96Smrg			return (cmp_br_fi(OBR(op1), OFI(op2)));
27055dfecf96Smrg		    case LispInteger_t:
27065dfecf96Smrg			return (cmp_br_fi(OBR(op1), OII(op2)));
27075dfecf96Smrg		    case LispBignum_t:
27085dfecf96Smrg			return (cmp_br_bi(OBR(op1), OBI(op2)));
27095dfecf96Smrg		    case LispDFloat_t:
27105dfecf96Smrg			return (cmp_flonum(br_getd(OBR(op1)), ODF(op2)));
27115dfecf96Smrg		    case LispRatio_t:
27125dfecf96Smrg			return (cmp_br_fr(OBR(op1), OFRN(op2), OFRD(op2)));
27135dfecf96Smrg		    case LispBigratio_t:
27145dfecf96Smrg			return (cmp_br_br(OBR(op1), OBR(op2)));
27155dfecf96Smrg		    default:
27165dfecf96Smrg			break;
27175dfecf96Smrg		}
27185dfecf96Smrg		break;
27195dfecf96Smrg	    default:
27205dfecf96Smrg		fatal_object_error(op1, NOT_A_NUMBER);
27215dfecf96Smrg		break;
27225dfecf96Smrg	}
27235dfecf96Smrg    }
27245dfecf96Smrg
27255dfecf96Smrg    fatal_object_error(op2, NOT_A_NUMBER);
27265dfecf96Smrg    return (0);
27275dfecf96Smrg}
27285dfecf96Smrg
27295dfecf96Smrg
27305dfecf96Smrg/************************************************************************
27315dfecf96Smrg * FIXNUM
27325dfecf96Smrg ************************************************************************/
27335dfecf96Smrg/*
27345dfecf96Smrg * check if op1 + op2 will overflow
27355dfecf96Smrg */
27365dfecf96Smrgstatic INLINE int
27375dfecf96Smrgfi_fi_add_overflow(long op1, long op2)
27385dfecf96Smrg{
27395dfecf96Smrg    long op = op1 + op2;
27405dfecf96Smrg
27415dfecf96Smrg    return (op1 > 0 ? op2 > op : op2 < op);
27425dfecf96Smrg}
27435dfecf96Smrg
27445dfecf96Smrg/*
27455dfecf96Smrg * check if op1 - op2 will overflow
27465dfecf96Smrg */
27475dfecf96Smrgstatic INLINE int
27485dfecf96Smrgfi_fi_sub_overflow(long op1, long op2)
27495dfecf96Smrg{
27505dfecf96Smrg    long op = op1 - op2;
27515dfecf96Smrg
27525dfecf96Smrg    return (((op1 < 0) ^ (op2 < 0)) && ((op < 0) ^ (op1 < 0)));
27535dfecf96Smrg}
27545dfecf96Smrg
27555dfecf96Smrg/*
27565dfecf96Smrg * check if op1 * op2 will overflow
27575dfecf96Smrg */
27585dfecf96Smrgstatic INLINE int
27595dfecf96Smrgfi_fi_mul_overflow(long op1, long op2)
27605dfecf96Smrg{
27615dfecf96Smrg#ifndef LONG64
27625dfecf96Smrg    double op = (double)op1 * (double)op2;
27635dfecf96Smrg
27645dfecf96Smrg    return (op > 2147483647.0 || op < -2147483648.0);
27655dfecf96Smrg#else
27665dfecf96Smrg    int shift;
27675dfecf96Smrg    long mask;
27685dfecf96Smrg
27695dfecf96Smrg    if (op1 == 0 || op1 == 1 || op2 == 0 || op2 == 1)
27705dfecf96Smrg	return (0);
27715dfecf96Smrg
27725dfecf96Smrg    if (op1 == MINSLONG || op2 == MINSLONG)
27735dfecf96Smrg	return (1);
27745dfecf96Smrg
27755dfecf96Smrg    if (op1 < 0)
27765dfecf96Smrg	op1 = -op1;
27775dfecf96Smrg    if (op2 < 0)
27785dfecf96Smrg	op2 = -op2;
27795dfecf96Smrg
27805dfecf96Smrg    for (shift = 0, mask = FI_MASK; shift < LONGSBITS; shift++, mask >>= 1)
27815dfecf96Smrg	if (op1 & mask)
27825dfecf96Smrg	    break;
27835dfecf96Smrg    ++shift;
27845dfecf96Smrg    for (mask = FI_MASK; shift < LONGSBITS; shift++, mask >>= 1)
27855dfecf96Smrg	if (op2 & mask)
27865dfecf96Smrg	    break;
27875dfecf96Smrg
27885dfecf96Smrg    return (shift < LONGSBITS);
27895dfecf96Smrg#endif
27905dfecf96Smrg}
27915dfecf96Smrg
27925dfecf96Smrg
27935dfecf96Smrg/************************************************************************
27945dfecf96Smrg * BIGNUM
27955dfecf96Smrg ************************************************************************/
27965dfecf96Smrgstatic void
27975dfecf96Smrgrbi_canonicalize(n_real *real)
27985dfecf96Smrg{
27995dfecf96Smrg    if (mpi_fiti(RBI(real))) {
28005dfecf96Smrg	long fi = mpi_geti(RBI(real));
28015dfecf96Smrg
28025dfecf96Smrg	RTYPE(real) = N_FIXNUM;
28035dfecf96Smrg	mpi_clear(RBI(real));
28045dfecf96Smrg	XFREE(RBI(real));
28055dfecf96Smrg	RFI(real) = fi;
28065dfecf96Smrg    }
28075dfecf96Smrg}
28085dfecf96Smrg
28095dfecf96Smrg
28105dfecf96Smrg/************************************************************************
28115dfecf96Smrg * RATIO
28125dfecf96Smrg ************************************************************************/
28135dfecf96Smrgstatic void
28145dfecf96Smrgrfr_canonicalize(n_real *real)
28155dfecf96Smrg{
28165dfecf96Smrg    long num, numerator, den, denominator, rest;
28175dfecf96Smrg
28185dfecf96Smrg    num = numerator = RFRN(real);
28195dfecf96Smrg    den = denominator = RFRD(real);
28205dfecf96Smrg    if (denominator == 0)
28215dfecf96Smrg	fatal_error(DIVIDE_BY_ZERO);
28225dfecf96Smrg
28235dfecf96Smrg    if (num == MINSLONG || den == MINSLONG) {
28245dfecf96Smrg	mpr *bigratio = XALLOC(mpr);
28255dfecf96Smrg
28265dfecf96Smrg	mpr_init(bigratio);
28275dfecf96Smrg	mpr_seti(bigratio, num, den);
28285dfecf96Smrg	RTYPE(real) = N_BIGRATIO;
28295dfecf96Smrg	RBR(real) = bigratio;
28305dfecf96Smrg	rbr_canonicalize(real);
28315dfecf96Smrg	return;
28325dfecf96Smrg    }
28335dfecf96Smrg
28345dfecf96Smrg    if (num < 0)
28355dfecf96Smrg	num = -num;
28365dfecf96Smrg    else if (num == 0) {
28375dfecf96Smrg	RFI(real) = 0;
28385dfecf96Smrg	RTYPE(real) = N_FIXNUM;
28395dfecf96Smrg	return;
28405dfecf96Smrg    }
28415dfecf96Smrg    for (;;) {
28425dfecf96Smrg	if ((rest = den % num) == 0)
28435dfecf96Smrg	    break;
28445dfecf96Smrg	den = num;
28455dfecf96Smrg	num = rest;
28465dfecf96Smrg    }
28475dfecf96Smrg    if (den != 1) {
28485dfecf96Smrg	denominator /= num;
28495dfecf96Smrg	numerator /= num;
28505dfecf96Smrg    }
28515dfecf96Smrg    if (denominator < 0) {
28525dfecf96Smrg	numerator = -numerator;
28535dfecf96Smrg	denominator = -denominator;
28545dfecf96Smrg    }
28555dfecf96Smrg    if (denominator == 1) {
28565dfecf96Smrg	RTYPE(real) = N_FIXNUM;
28575dfecf96Smrg	RFI(real) = numerator;
28585dfecf96Smrg    }
28595dfecf96Smrg    else {
28605dfecf96Smrg	RFRN(real) = numerator;
28615dfecf96Smrg	RFRD(real) = denominator;
28625dfecf96Smrg    }
28635dfecf96Smrg}
28645dfecf96Smrg
28655dfecf96Smrgstatic void
28665dfecf96Smrgrbr_canonicalize(n_real *real)
28675dfecf96Smrg{
28685dfecf96Smrg    int fitnum, fitden;
28695dfecf96Smrg    long numerator, denominator;
28705dfecf96Smrg
28715dfecf96Smrg    mpr_canonicalize(RBR(real));
28725dfecf96Smrg    fitnum = mpi_fiti(RBRN(real));
28735dfecf96Smrg    fitden = mpi_fiti(RBRD(real));
28745dfecf96Smrg    if (fitnum && fitden) {
28755dfecf96Smrg	numerator = mpi_geti(RBRN(real));
28765dfecf96Smrg	denominator = mpi_geti(RBRD(real));
28775dfecf96Smrg	mpr_clear(RBR(real));
28785dfecf96Smrg	XFREE(RBR(real));
28795dfecf96Smrg	if (numerator == 0) {
28805dfecf96Smrg	    RFI(real) = 0;
28815dfecf96Smrg	    RTYPE(real) = N_FIXNUM;
28825dfecf96Smrg	}
28835dfecf96Smrg	else if (denominator == 1) {
28845dfecf96Smrg	    RTYPE(real) = N_FIXNUM;
28855dfecf96Smrg	    RFI(real) = numerator;
28865dfecf96Smrg	}
28875dfecf96Smrg	else {
28885dfecf96Smrg	    RTYPE(real) = N_FIXRATIO;
28895dfecf96Smrg	    RFRN(real) = numerator;
28905dfecf96Smrg	    RFRD(real) = denominator;
28915dfecf96Smrg	}
28925dfecf96Smrg    }
28935dfecf96Smrg    else if (fitden) {
28945dfecf96Smrg	denominator = mpi_geti(RBRD(real));
28955dfecf96Smrg	if (denominator == 1) {
28965dfecf96Smrg	    mpi *bigi = XALLOC(mpi);
28975dfecf96Smrg
28985dfecf96Smrg	    mpi_init(bigi);
28995dfecf96Smrg	    mpi_set(bigi, RBRN(real));
29005dfecf96Smrg	    mpr_clear(RBR(real));
29015dfecf96Smrg	    XFREE(RBR(real));
29025dfecf96Smrg	    RTYPE(real) = N_BIGNUM;
29035dfecf96Smrg	    RBI(real) = bigi;
29045dfecf96Smrg	}
29055dfecf96Smrg	else if (denominator == 0)
29065dfecf96Smrg	    fatal_error(DIVIDE_BY_ZERO);
29075dfecf96Smrg    }
29085dfecf96Smrg}
29095dfecf96Smrg
29105dfecf96Smrg
29115dfecf96Smrg/************************************************************************
29125dfecf96Smrg * COMPLEX
29135dfecf96Smrg ************************************************************************/
29145dfecf96Smrgstatic void
29155dfecf96Smrgncx_canonicalize(n_number *num)
29165dfecf96Smrg{
29175dfecf96Smrg    if (NITYPE(num) == N_FIXNUM && NIFI(num) == 0)
29185dfecf96Smrg	num->complex = 0;
29195dfecf96Smrg}
29205dfecf96Smrg
29215dfecf96Smrg
29225dfecf96Smrg/************************************************************************
29235dfecf96Smrg * DIVIDE
29245dfecf96Smrg ************************************************************************/
29255dfecf96Smrg#define NDIVIDE_NOP	0
29265dfecf96Smrg#define NDIVIDE_ADD	1
29275dfecf96Smrg#define NDIVIDE_SUB	2
29285dfecf96Smrgstatic void
29295dfecf96Smrgndivide_fi_fi(n_number *num, long div, int fun, int flo)
29305dfecf96Smrg{
29315dfecf96Smrg    long quo, rem;
29325dfecf96Smrg
29335dfecf96Smrg    if (NRFI(num) == MINSLONG || div == MINSLONG) {
29345dfecf96Smrg	LispObj integer;
29355dfecf96Smrg	mpi *bignum = XALLOC(mpi);
29365dfecf96Smrg
29375dfecf96Smrg	mpi_init(bignum);
29385dfecf96Smrg	mpi_seti(bignum, NRFI(num));
29395dfecf96Smrg	NRBI(num) = bignum;
29405dfecf96Smrg	NRTYPE(num) = N_BIGNUM;
29415dfecf96Smrg	integer.type = LispInteger_t;
29425dfecf96Smrg	integer.data.integer = div;
29435dfecf96Smrg	ndivide_xi_xi(num, &integer, fun, flo);
29445dfecf96Smrg	return;
29455dfecf96Smrg    }
29465dfecf96Smrg    else {
29475dfecf96Smrg	quo = NRFI(num) / div;
29485dfecf96Smrg	rem = NRFI(num) % div;
29495dfecf96Smrg    }
29505dfecf96Smrg
29515dfecf96Smrg    switch (fun) {
29525dfecf96Smrg	case NDIVIDE_CEIL:
29535dfecf96Smrg	    if ((rem < 0 && div < 0) || (rem > 0 && div > 0)) {
29545dfecf96Smrg		++quo;
29555dfecf96Smrg		rem -= div;
29565dfecf96Smrg	    }
29575dfecf96Smrg	    break;
29585dfecf96Smrg	case NDIVIDE_FLOOR:
29595dfecf96Smrg	    if ((rem < 0 && div > 0) || (rem > 0 && div < 0)) {
29605dfecf96Smrg		--quo;
29615dfecf96Smrg		rem += div;
29625dfecf96Smrg	    }
29635dfecf96Smrg	    break;
29645dfecf96Smrg	case NDIVIDE_ROUND:
29655dfecf96Smrg	    if (div > 0) {
29665dfecf96Smrg		if (rem > 0) {
29675dfecf96Smrg		    if (rem >= (div + 1) / 2) {
29685dfecf96Smrg			++quo;
29695dfecf96Smrg			rem -= div;
29705dfecf96Smrg		    }
29715dfecf96Smrg		}
29725dfecf96Smrg		else {
29735dfecf96Smrg		    if (rem <= (-div - 1) / 2) {
29745dfecf96Smrg			--quo;
29755dfecf96Smrg			rem += div;
29765dfecf96Smrg		    }
29775dfecf96Smrg		}
29785dfecf96Smrg	    }
29795dfecf96Smrg	    else {
29805dfecf96Smrg		if (rem > 0) {
29815dfecf96Smrg		    if (rem >= (-div + 1) / 2) {
29825dfecf96Smrg			--quo;
29835dfecf96Smrg			rem += div;
29845dfecf96Smrg		    }
29855dfecf96Smrg		}
29865dfecf96Smrg		else {
29875dfecf96Smrg		    if (rem <= (div - 1) / 2) {
29885dfecf96Smrg			++quo;
29895dfecf96Smrg			rem -= div;
29905dfecf96Smrg		    }
29915dfecf96Smrg		}
29925dfecf96Smrg	    }
29935dfecf96Smrg	    break;
29945dfecf96Smrg    }
29955dfecf96Smrg
29965dfecf96Smrg    NITYPE(num) = N_FIXNUM;
29975dfecf96Smrg    NIFI(num) = rem;
29985dfecf96Smrg    if (flo) {
29995dfecf96Smrg	NRTYPE(num) = N_FLONUM;
30005dfecf96Smrg	NRFF(num) = (double)quo;
30015dfecf96Smrg    }
30025dfecf96Smrg    else
30035dfecf96Smrg	NRFI(num) = quo;
30045dfecf96Smrg}
30055dfecf96Smrg
30065dfecf96Smrgstatic void
30075dfecf96Smrgndivide_xi_xi(n_number *num, LispObj *div, int fun, int flo)
30085dfecf96Smrg{
30095dfecf96Smrg    LispType type = OBJECT_TYPE(div);
30105dfecf96Smrg    int state = NDIVIDE_NOP, dsign, rsign;
30115dfecf96Smrg    mpi *quo, *rem;
30125dfecf96Smrg
30135dfecf96Smrg    quo = XALLOC(mpi);
30145dfecf96Smrg    mpi_init(quo);
30155dfecf96Smrg    if (NRTYPE(num) == N_FIXNUM)
30165dfecf96Smrg	mpi_seti(quo, NRFI(num));
30175dfecf96Smrg    else
30185dfecf96Smrg	mpi_set(quo, NRBI(num));
30195dfecf96Smrg
30205dfecf96Smrg    rem = XALLOC(mpi);
30215dfecf96Smrg    mpi_init(rem);
30225dfecf96Smrg
30235dfecf96Smrg    switch (type) {
30245dfecf96Smrg	case LispFixnum_t:
30255dfecf96Smrg	    mpi_seti(rem, OFI(div));
30265dfecf96Smrg	    break;
30275dfecf96Smrg	case LispInteger_t:
30285dfecf96Smrg	    mpi_seti(rem, OII(div));
30295dfecf96Smrg	    break;
30305dfecf96Smrg	default:
30315dfecf96Smrg	    mpi_set(rem, OBI(div));
30325dfecf96Smrg    }
30335dfecf96Smrg
30345dfecf96Smrg    dsign = mpi_sgn(rem);
30355dfecf96Smrg
30365dfecf96Smrg    mpi_divqr(quo, rem, quo, rem);
30375dfecf96Smrg    rsign = mpi_sgn(rem);
30385dfecf96Smrg
30395dfecf96Smrg    switch (fun) {
30405dfecf96Smrg	case NDIVIDE_CEIL:
30415dfecf96Smrg	    if ((rsign < 0 && dsign < 0) || (rsign > 0 && dsign > 0))
30425dfecf96Smrg		state = NDIVIDE_ADD;
30435dfecf96Smrg	    break;
30445dfecf96Smrg	case NDIVIDE_FLOOR:
30455dfecf96Smrg	    if ((rsign < 0 && dsign > 0) || (rsign > 0 && dsign < 0))
30465dfecf96Smrg		state = NDIVIDE_SUB;
30475dfecf96Smrg	    break;
30485dfecf96Smrg	case NDIVIDE_ROUND: {
30495dfecf96Smrg	    mpi test;
30505dfecf96Smrg
30515dfecf96Smrg	    mpi_init(&test);
30525dfecf96Smrg	    switch (type) {
30535dfecf96Smrg		case LispFixnum_t:
30545dfecf96Smrg		    mpi_seti(&test, OFI(div));
30555dfecf96Smrg		    break;
30565dfecf96Smrg		case LispInteger_t:
30575dfecf96Smrg		    mpi_seti(&test, OII(div));
30585dfecf96Smrg		    break;
30595dfecf96Smrg		default:
30605dfecf96Smrg		    mpi_set(&test, OBI(div));
30615dfecf96Smrg	    }
30625dfecf96Smrg	    if (dsign > 0) {
30635dfecf96Smrg		if (rsign > 0) {
30645dfecf96Smrg		    mpi_addi(&test, &test, 1);
30655dfecf96Smrg		    mpi_divi(&test, &test, 2);
30665dfecf96Smrg		    if (mpi_cmp(rem, &test) >= 0)
30675dfecf96Smrg			state = NDIVIDE_ADD;
30685dfecf96Smrg		}
30695dfecf96Smrg		else {
30705dfecf96Smrg		    mpi_neg(&test, &test);
30715dfecf96Smrg		    mpi_subi(&test, &test, 1);
30725dfecf96Smrg		    mpi_divi(&test, &test, 2);
30735dfecf96Smrg		    if (mpi_cmp(rem, &test) <= 0)
30745dfecf96Smrg			state = NDIVIDE_SUB;
30755dfecf96Smrg		}
30765dfecf96Smrg	    }
30775dfecf96Smrg	    else {
30785dfecf96Smrg		if (rsign > 0) {
30795dfecf96Smrg		    mpi_neg(&test, &test);
30805dfecf96Smrg		    mpi_addi(&test, &test, 1);
30815dfecf96Smrg		    mpi_divi(&test, &test, 2);
30825dfecf96Smrg		    if (mpi_cmp(rem, &test) >= 0)
30835dfecf96Smrg			state = NDIVIDE_SUB;
30845dfecf96Smrg		}
30855dfecf96Smrg		else {
30865dfecf96Smrg		    mpi_subi(&test, &test, 1);
30875dfecf96Smrg		    mpi_divi(&test, &test, 2);
30885dfecf96Smrg		    if (mpi_cmp(rem, &test) <= 0)
30895dfecf96Smrg			state = NDIVIDE_ADD;
30905dfecf96Smrg		}
30915dfecf96Smrg	    }
30925dfecf96Smrg	    mpi_clear(&test);
30935dfecf96Smrg	}   break;
30945dfecf96Smrg    }
30955dfecf96Smrg
30965dfecf96Smrg    if (state == NDIVIDE_ADD) {
30975dfecf96Smrg	mpi_addi(quo, quo, 1);
30985dfecf96Smrg	switch (type) {
30995dfecf96Smrg	    case LispFixnum_t:
31005dfecf96Smrg		mpi_subi(rem, rem, OFI(div));
31015dfecf96Smrg		break;
31025dfecf96Smrg	    case LispInteger_t:
31035dfecf96Smrg		mpi_subi(rem, rem, OII(div));
31045dfecf96Smrg		break;
31055dfecf96Smrg	    default:
31065dfecf96Smrg		mpi_sub(rem, rem, OBI(div));
31075dfecf96Smrg	}
31085dfecf96Smrg    }
31095dfecf96Smrg    else if (state == NDIVIDE_SUB) {
31105dfecf96Smrg	mpi_subi(quo, quo, 1);
31115dfecf96Smrg	switch (type) {
31125dfecf96Smrg	    case LispFixnum_t:
31135dfecf96Smrg		mpi_addi(rem, rem, OFI(div));
31145dfecf96Smrg		break;
31155dfecf96Smrg	    case LispInteger_t:
31165dfecf96Smrg		mpi_addi(rem, rem, OII(div));
31175dfecf96Smrg		break;
31185dfecf96Smrg	    default:
31195dfecf96Smrg		mpi_add(rem, rem, OBI(div));
31205dfecf96Smrg	}
31215dfecf96Smrg    }
31225dfecf96Smrg
31235dfecf96Smrg    if (mpi_fiti(rem)) {
31245dfecf96Smrg	NITYPE(num) = N_FIXNUM;
31255dfecf96Smrg	NIFI(num) = mpi_geti(rem);
31265dfecf96Smrg	mpi_clear(rem);
31275dfecf96Smrg	XFREE(rem);
31285dfecf96Smrg    }
31295dfecf96Smrg    else {
31305dfecf96Smrg	NITYPE(num) = N_BIGNUM;
31315dfecf96Smrg	NIBI(num) = rem;
31325dfecf96Smrg    }
31335dfecf96Smrg
31345dfecf96Smrg    clear_real(NREAL(num));
31355dfecf96Smrg
31365dfecf96Smrg    if (flo) {
31375dfecf96Smrg	double dval = bi_getd(quo);
31385dfecf96Smrg
31395dfecf96Smrg	mpi_clear(quo);
31405dfecf96Smrg	XFREE(quo);
31415dfecf96Smrg	NRTYPE(num) = N_FLONUM;
31425dfecf96Smrg	NRFF(num) = dval;
31435dfecf96Smrg    }
31445dfecf96Smrg    else {
31455dfecf96Smrg	NRTYPE(num) = N_BIGNUM;
31465dfecf96Smrg	NRBI(num) = quo;
31475dfecf96Smrg	rbi_canonicalize(NREAL(num));
31485dfecf96Smrg    }
31495dfecf96Smrg}
31505dfecf96Smrg
31515dfecf96Smrgstatic void
31525dfecf96Smrgndivide_flonum(n_number *number, double num, double div, int fun, int flo)
31535dfecf96Smrg{
31545dfecf96Smrg    double quo, rem, modp, tmp;
31555dfecf96Smrg
31565dfecf96Smrg    modp = modf(num / div, &quo);
31575dfecf96Smrg    rem = num - quo * div;
31585dfecf96Smrg
31595dfecf96Smrg    switch (fun) {
31605dfecf96Smrg	case NDIVIDE_CEIL:
31615dfecf96Smrg	    if ((rem < 0.0 && div < 0.0) || (rem > 0.0 && div > 0.0)) {
31625dfecf96Smrg		quo += 1.0;
31635dfecf96Smrg		rem -= div;
31645dfecf96Smrg	    }
31655dfecf96Smrg	    break;
31665dfecf96Smrg	case NDIVIDE_FLOOR:
31675dfecf96Smrg	    if ((rem < 0.0 && div > 0.0) || (rem > 0.0 && div < 0.0)) {
31685dfecf96Smrg		quo -= 1.0;
31695dfecf96Smrg		rem += div;
31705dfecf96Smrg	    }
31715dfecf96Smrg	    break;
31725dfecf96Smrg	case NDIVIDE_ROUND:
31735dfecf96Smrg	    if (fabs(modp) != 0.5 || modf(quo * 0.5, &tmp) != 0.0) {
31745dfecf96Smrg		if (div > 0.0) {
31755dfecf96Smrg		    if (rem > 0.0) {
31765dfecf96Smrg			if (rem >= div * 0.5) {
31775dfecf96Smrg			    quo += 1.0;
31785dfecf96Smrg			    rem -= div;
31795dfecf96Smrg			}
31805dfecf96Smrg		    }
31815dfecf96Smrg		    else {
31825dfecf96Smrg			if (rem <= div * -0.5) {
31835dfecf96Smrg			    quo -= 1.0;
31845dfecf96Smrg			    rem += div;
31855dfecf96Smrg			}
31865dfecf96Smrg		    }
31875dfecf96Smrg		}
31885dfecf96Smrg		else {
31895dfecf96Smrg		    if (rem > 0.0) {
31905dfecf96Smrg			if (rem >= div * -0.5) {
31915dfecf96Smrg			    quo -= 1.0;
31925dfecf96Smrg			    rem += div;
31935dfecf96Smrg			}
31945dfecf96Smrg		    }
31955dfecf96Smrg		    else {
31965dfecf96Smrg			if (rem <= div * 0.5) {
31975dfecf96Smrg			    quo += 1.0;
31985dfecf96Smrg			    rem -= div;
31995dfecf96Smrg			}
32005dfecf96Smrg		    }
32015dfecf96Smrg		}
32025dfecf96Smrg	    }
32035dfecf96Smrg	    break;
32045dfecf96Smrg    }
32055dfecf96Smrg    if (!finite(quo) || !finite(rem))
32065dfecf96Smrg	fatal_error(FLOATING_POINT_OVERFLOW);
32075dfecf96Smrg
32085dfecf96Smrg    NITYPE(number) = N_FLONUM;
32095dfecf96Smrg    NIFF(number) = rem;
32105dfecf96Smrg
32115dfecf96Smrg    clear_real(NREAL(number));
32125dfecf96Smrg
32135dfecf96Smrg    if (flo) {
32145dfecf96Smrg	NRTYPE(number) = N_FLONUM;
32155dfecf96Smrg	NRFF(number) = quo;
32165dfecf96Smrg    }
32175dfecf96Smrg    else {
32185dfecf96Smrg	if ((long)quo == quo) {
32195dfecf96Smrg	    NRTYPE(number) = N_FIXNUM;
32205dfecf96Smrg	    NRFI(number) = (long)quo;
32215dfecf96Smrg	}
32225dfecf96Smrg	else {
32235dfecf96Smrg	    mpi *bigi = XALLOC(mpi);
32245dfecf96Smrg
32255dfecf96Smrg	    mpi_init(bigi);
32265dfecf96Smrg	    mpi_setd(bigi, quo);
32275dfecf96Smrg	    NRBI(number) = bigi;
32285dfecf96Smrg	    NRTYPE(number) = N_BIGNUM;
32295dfecf96Smrg	}
32305dfecf96Smrg    }
32315dfecf96Smrg}
32325dfecf96Smrg
32335dfecf96Smrgstatic void
32345dfecf96Smrgndivide_xi_xr(n_number *num, LispObj *div, int fun, int flo)
32355dfecf96Smrg{
32365dfecf96Smrg    int state = NDIVIDE_NOP, dsign, rsign;
32375dfecf96Smrg    mpi *quo;
32385dfecf96Smrg    mpr *rem;
32395dfecf96Smrg
32405dfecf96Smrg    quo = XALLOC(mpi);
32415dfecf96Smrg    mpi_init(quo);
32425dfecf96Smrg    if (NRTYPE(num) == N_FIXNUM)
32435dfecf96Smrg	mpi_seti(quo, NRFI(num));
32445dfecf96Smrg    else
32455dfecf96Smrg	mpi_set(quo, NRBI(num));
32465dfecf96Smrg
32475dfecf96Smrg    rem = XALLOC(mpr);
32485dfecf96Smrg    mpr_init(rem);
32495dfecf96Smrg
32505dfecf96Smrg    if (XOBJECT_TYPE(div) == LispRatio_t)
32515dfecf96Smrg	mpr_seti(rem, OFRN(div), OFRD(div));
32525dfecf96Smrg    else
32535dfecf96Smrg	mpr_set(rem, OBR(div));
32545dfecf96Smrg    dsign = mpi_sgn(mpr_num(rem));
32555dfecf96Smrg    mpi_mul(quo, quo, mpr_den(rem));
32565dfecf96Smrg
32575dfecf96Smrg    mpi_divqr(quo, mpr_num(rem), quo, mpr_num(rem));
32585dfecf96Smrg    mpr_canonicalize(rem);
32595dfecf96Smrg
32605dfecf96Smrg    rsign = mpi_sgn(mpr_num(rem));
32615dfecf96Smrg    if (mpr_fiti(rem)) {
32625dfecf96Smrg	if (mpi_geti(mpr_den(rem)) == 1) {
32635dfecf96Smrg	    NITYPE(num) = N_FIXNUM;
32645dfecf96Smrg	    NIFI(num) = mpi_geti(mpr_num(rem));
32655dfecf96Smrg	}
32665dfecf96Smrg	else {
32675dfecf96Smrg	    NITYPE(num) = N_FIXRATIO;
32685dfecf96Smrg	    NIFRN(num) = mpi_geti(mpr_num(rem));
32695dfecf96Smrg	    NIFRD(num) = mpi_geti(mpr_den(rem));
32705dfecf96Smrg	}
32715dfecf96Smrg	mpr_clear(rem);
32725dfecf96Smrg	XFREE(rem);
32735dfecf96Smrg    }
32745dfecf96Smrg    else {
32755dfecf96Smrg	if (mpi_fiti(mpr_den(rem)) && mpi_geti(mpr_den(rem)) == 1) {
32765dfecf96Smrg	    NITYPE(num) = N_BIGNUM;
32775dfecf96Smrg	    NIBI(num) = mpr_num(rem);
32785dfecf96Smrg	    mpi_clear(mpr_den(rem));
32795dfecf96Smrg	    XFREE(rem);
32805dfecf96Smrg	}
32815dfecf96Smrg	else {
32825dfecf96Smrg	    NITYPE(num) = N_BIGRATIO;
32835dfecf96Smrg	    NIBR(num) = rem;
32845dfecf96Smrg	}
32855dfecf96Smrg    }
32865dfecf96Smrg
32875dfecf96Smrg    switch (fun) {
32885dfecf96Smrg	case NDIVIDE_CEIL:
32895dfecf96Smrg	    if ((rsign < 0 && dsign < 0) || (rsign > 0 && dsign > 0))
32905dfecf96Smrg		state = NDIVIDE_ADD;
32915dfecf96Smrg	    break;
32925dfecf96Smrg	case NDIVIDE_FLOOR:
32935dfecf96Smrg	    if ((rsign < 0 && dsign > 0) || (rsign > 0 && dsign < 0))
32945dfecf96Smrg		state = NDIVIDE_SUB;
32955dfecf96Smrg	    break;
32965dfecf96Smrg	case NDIVIDE_ROUND: {
32975dfecf96Smrg	    n_real cmp;
32985dfecf96Smrg
32995dfecf96Smrg	    set_real_object(&cmp, div);
33005dfecf96Smrg	    div_real_real(&cmp, &two);
33015dfecf96Smrg	    if (dsign > 0) {
33025dfecf96Smrg		if (rsign > 0) {
33035dfecf96Smrg		    if (cmp_real_real(NIMAG(num), &cmp) >= 0)
33045dfecf96Smrg			state = NDIVIDE_ADD;
33055dfecf96Smrg		}
33065dfecf96Smrg		else {
33075dfecf96Smrg		    neg_real(&cmp);
33085dfecf96Smrg		    if (cmp_real_real(NIMAG(num), &cmp) <= 0)
33095dfecf96Smrg			state = NDIVIDE_SUB;
33105dfecf96Smrg		}
33115dfecf96Smrg	    }
33125dfecf96Smrg	    else {
33135dfecf96Smrg		if (rsign > 0) {
33145dfecf96Smrg		    neg_real(&cmp);
33155dfecf96Smrg		    if (cmp_real_real(NIMAG(num), &cmp) >= 0)
33165dfecf96Smrg			state = NDIVIDE_SUB;
33175dfecf96Smrg		}
33185dfecf96Smrg		else {
33195dfecf96Smrg		    if (cmp_real_real(NIMAG(num), &cmp) <= 0)
33205dfecf96Smrg			state = NDIVIDE_ADD;
33215dfecf96Smrg		}
33225dfecf96Smrg	    }
33235dfecf96Smrg	    clear_real(&cmp);
33245dfecf96Smrg	}   break;
33255dfecf96Smrg    }
33265dfecf96Smrg
33275dfecf96Smrg    if (state == NDIVIDE_ADD) {
33285dfecf96Smrg	mpi_addi(quo, quo, 1);
33295dfecf96Smrg	sub_real_object(NIMAG(num), div);
33305dfecf96Smrg    }
33315dfecf96Smrg    else if (state == NDIVIDE_SUB) {
33325dfecf96Smrg	mpi_subi(quo, quo, 1);
33335dfecf96Smrg	add_real_object(NIMAG(num), div);
33345dfecf96Smrg    }
33355dfecf96Smrg
33365dfecf96Smrg    clear_real(NREAL(num));
33375dfecf96Smrg
33385dfecf96Smrg    if (flo) {
33395dfecf96Smrg	double dval = bi_getd(quo);
33405dfecf96Smrg
33415dfecf96Smrg	mpi_clear(quo);
33425dfecf96Smrg	XFREE(quo);
33435dfecf96Smrg	NRTYPE(num) = N_FLONUM;
33445dfecf96Smrg	NRFF(num) = dval;
33455dfecf96Smrg    }
33465dfecf96Smrg    else {
33475dfecf96Smrg	NRBI(num)  = quo;
33485dfecf96Smrg	NRTYPE(num) = N_BIGNUM;
33495dfecf96Smrg	rbi_canonicalize(NREAL(num));
33505dfecf96Smrg    }
33515dfecf96Smrg}
33525dfecf96Smrg
33535dfecf96Smrgstatic void
33545dfecf96Smrgndivide_xr_xi(n_number *num, LispObj *div, int fun, int flo)
33555dfecf96Smrg{
33565dfecf96Smrg    LispType type = OBJECT_TYPE(div);
33575dfecf96Smrg    int state = NDIVIDE_NOP, dsign, rsign;
33585dfecf96Smrg    mpi *quo;
33595dfecf96Smrg    mpr *rem;
33605dfecf96Smrg
33615dfecf96Smrg    quo = XALLOC(mpi);
33625dfecf96Smrg    mpi_init(quo);
33635dfecf96Smrg    switch (type) {
33645dfecf96Smrg	case LispFixnum_t:
33655dfecf96Smrg	    dsign = OFI(div) < 0 ? -1 : OFI(div) > 0 ? 1 : 0;
33665dfecf96Smrg	    mpi_seti(quo, OFI(div));
33675dfecf96Smrg	    break;
33685dfecf96Smrg	case LispInteger_t:
33695dfecf96Smrg	    dsign = OII(div) < 0 ? -1 : OII(div) > 0 ? 1 : 0;
33705dfecf96Smrg	    mpi_seti(quo, OII(div));
33715dfecf96Smrg	    break;
33725dfecf96Smrg	default:
33735dfecf96Smrg	    dsign = mpi_sgn(OBI(div));
33745dfecf96Smrg	    mpi_set(quo, OBI(div));
33755dfecf96Smrg	    break;
33765dfecf96Smrg    }
33775dfecf96Smrg
33785dfecf96Smrg    rem = XALLOC(mpr);
33795dfecf96Smrg    mpr_init(rem);
33805dfecf96Smrg    if (NRTYPE(num) == N_FIXRATIO) {
33815dfecf96Smrg	mpr_seti(rem, NRFRN(num), NRFRD(num));
33825dfecf96Smrg	mpi_muli(quo, quo, NRFRD(num));
33835dfecf96Smrg    }
33845dfecf96Smrg    else {
33855dfecf96Smrg	mpr_set(rem, NRBR(num));
33865dfecf96Smrg	mpi_mul(quo, quo, NRBRD(num));
33875dfecf96Smrg    }
33885dfecf96Smrg    mpi_divqr(quo, mpr_num(rem), mpr_num(rem), quo);
33895dfecf96Smrg    mpr_canonicalize(rem);
33905dfecf96Smrg
33915dfecf96Smrg    rsign = mpi_sgn(mpr_num(rem));
33925dfecf96Smrg    if (mpr_fiti(rem)) {
33935dfecf96Smrg	NITYPE(num) = N_FIXRATIO;
33945dfecf96Smrg	NIFRN(num) = mpi_geti(mpr_num(rem));
33955dfecf96Smrg	NIFRD(num) = mpi_geti(mpr_den(rem));
33965dfecf96Smrg	mpr_clear(rem);
33975dfecf96Smrg	XFREE(rem);
33985dfecf96Smrg    }
33995dfecf96Smrg    else {
34005dfecf96Smrg	NITYPE(num) = N_BIGRATIO;
34015dfecf96Smrg	NIBR(num) = rem;
34025dfecf96Smrg    }
34035dfecf96Smrg
34045dfecf96Smrg    switch (fun) {
34055dfecf96Smrg	case NDIVIDE_CEIL:
34065dfecf96Smrg	    if ((rsign < 0 && dsign < 0) || (rsign > 0 && dsign > 0))
34075dfecf96Smrg		state = NDIVIDE_ADD;
34085dfecf96Smrg	    break;
34095dfecf96Smrg	case NDIVIDE_FLOOR:
34105dfecf96Smrg	    if ((rsign < 0 && dsign > 0) || (rsign > 0 && dsign < 0))
34115dfecf96Smrg		state = NDIVIDE_SUB;
34125dfecf96Smrg	    break;
34135dfecf96Smrg	case NDIVIDE_ROUND: {
34145dfecf96Smrg	    n_real cmp;
34155dfecf96Smrg
34165dfecf96Smrg	    set_real_object(&cmp, div);
34175dfecf96Smrg	    div_real_real(&cmp, &two);
34185dfecf96Smrg	    if (dsign > 0) {
34195dfecf96Smrg		if (rsign > 0) {
34205dfecf96Smrg		    if (cmp_real_real(NIMAG(num), &cmp) >= 0)
34215dfecf96Smrg			state = NDIVIDE_ADD;
34225dfecf96Smrg		}
34235dfecf96Smrg		else {
34245dfecf96Smrg		    neg_real(&cmp);
34255dfecf96Smrg		    if (cmp_real_real(NIMAG(num), &cmp) <= 0)
34265dfecf96Smrg			state = NDIVIDE_SUB;
34275dfecf96Smrg		}
34285dfecf96Smrg	    }
34295dfecf96Smrg	    else {
34305dfecf96Smrg		if (rsign > 0) {
34315dfecf96Smrg		    neg_real(&cmp);
34325dfecf96Smrg		    if (cmp_real_real(NIMAG(num), &cmp) >= 0)
34335dfecf96Smrg			state = NDIVIDE_SUB;
34345dfecf96Smrg		}
34355dfecf96Smrg		else {
34365dfecf96Smrg		    if (cmp_real_real(NIMAG(num), &cmp) <= 0)
34375dfecf96Smrg			state = NDIVIDE_ADD;
34385dfecf96Smrg		}
34395dfecf96Smrg	    }
34405dfecf96Smrg	    clear_real(&cmp);
34415dfecf96Smrg	}   break;
34425dfecf96Smrg    }
34435dfecf96Smrg
34445dfecf96Smrg    if (state == NDIVIDE_ADD) {
34455dfecf96Smrg	mpi_addi(quo, quo, 1);
34465dfecf96Smrg	sub_real_object(NIMAG(num), div);
34475dfecf96Smrg    }
34485dfecf96Smrg    else if (state == NDIVIDE_SUB) {
34495dfecf96Smrg	mpi_subi(quo, quo, 1);
34505dfecf96Smrg	add_real_object(NIMAG(num), div);
34515dfecf96Smrg    }
34525dfecf96Smrg
34535dfecf96Smrg    clear_real(NREAL(num));
34545dfecf96Smrg
34555dfecf96Smrg    if (flo) {
34565dfecf96Smrg	double dval = bi_getd(quo);
34575dfecf96Smrg
34585dfecf96Smrg	mpi_clear(quo);
34595dfecf96Smrg	XFREE(quo);
34605dfecf96Smrg	NRTYPE(num) = N_FLONUM;
34615dfecf96Smrg	NRFF(num) = dval;
34625dfecf96Smrg    }
34635dfecf96Smrg    else {
34645dfecf96Smrg	NRBI(num) = quo;
34655dfecf96Smrg	NRTYPE(num) = N_BIGNUM;
34665dfecf96Smrg	rbi_canonicalize(NREAL(num));
34675dfecf96Smrg    }
34685dfecf96Smrg}
34695dfecf96Smrg
34705dfecf96Smrgstatic void
34715dfecf96Smrgndivide_xr_xr(n_number *num, LispObj *div, int fun, int flo)
34725dfecf96Smrg{
34735dfecf96Smrg    int state = NDIVIDE_NOP, dsign, rsign, modp;
34745dfecf96Smrg    mpr *bigr;
34755dfecf96Smrg    mpi *bigi;
34765dfecf96Smrg
34775dfecf96Smrg    bigr = XALLOC(mpr);
34785dfecf96Smrg    mpr_init(bigr);
34795dfecf96Smrg    if (NRTYPE(num) == N_FIXRATIO)
34805dfecf96Smrg	mpr_seti(bigr, NRFRN(num), NRFRD(num));
34815dfecf96Smrg    else
34825dfecf96Smrg	mpr_set(bigr, NRBR(num));
34835dfecf96Smrg
34845dfecf96Smrg    NITYPE(num) = N_BIGRATIO;
34855dfecf96Smrg    NIBR(num) = bigr;
34865dfecf96Smrg
34875dfecf96Smrg    if (OBJECT_TYPE(div) == LispRatio_t) {
34885dfecf96Smrg	dsign = OFRN(div) < 0 ? -1 : OFRN(div) > 0 ? 1 : 0;
34895dfecf96Smrg	mpi_muli(mpr_num(bigr), mpr_num(bigr), OFRD(div));
34905dfecf96Smrg	mpi_muli(mpr_den(bigr), mpr_den(bigr), OFRN(div));
34915dfecf96Smrg    }
34925dfecf96Smrg    else {
34935dfecf96Smrg	dsign = mpi_sgn(OBRN(div));
34945dfecf96Smrg	mpr_div(bigr, bigr, OBR(div));
34955dfecf96Smrg    }
34965dfecf96Smrg    modp = mpi_fiti(mpr_den(bigr)) && mpi_geti(mpr_den(bigr)) == 2;
34975dfecf96Smrg
34985dfecf96Smrg    bigi = XALLOC(mpi);
34995dfecf96Smrg    mpi_init(bigi);
35005dfecf96Smrg    mpi_divqr(bigi, mpr_num(bigr), mpr_num(bigr), mpr_den(bigr));
35015dfecf96Smrg
35025dfecf96Smrg    if (OBJECT_TYPE(div) == LispRatio_t)
35035dfecf96Smrg	mpi_seti(mpr_den(bigr), OFRD(div));
35045dfecf96Smrg    else
35055dfecf96Smrg	mpi_set(mpr_den(bigr), OBRD(div));
35065dfecf96Smrg    if (NRTYPE(num) == N_FIXRATIO)
35075dfecf96Smrg	mpi_muli(mpr_den(bigr), mpr_den(bigr), NRFRD(num));
35085dfecf96Smrg    else
35095dfecf96Smrg	mpi_mul(mpr_den(bigr), mpr_den(bigr), NRBRD(num));
35105dfecf96Smrg
35115dfecf96Smrg    clear_real(NREAL(num));
35125dfecf96Smrg    NRTYPE(num) = N_BIGNUM;
35135dfecf96Smrg    NRBI(num) = bigi;
35145dfecf96Smrg
35155dfecf96Smrg    rbr_canonicalize(NIMAG(num));
35165dfecf96Smrg    rsign = cmp_real_real(NIMAG(num), &zero);
35175dfecf96Smrg
35185dfecf96Smrg    switch (fun) {
35195dfecf96Smrg	case NDIVIDE_CEIL:
35205dfecf96Smrg	    if ((rsign < 0 && dsign < 0) || (rsign > 0 && dsign > 0))
35215dfecf96Smrg		state = NDIVIDE_ADD;
35225dfecf96Smrg	    break;
35235dfecf96Smrg	case NDIVIDE_FLOOR:
35245dfecf96Smrg	    if ((rsign < 0 && dsign > 0) || (rsign > 0 && dsign < 0))
35255dfecf96Smrg		state = NDIVIDE_SUB;
35265dfecf96Smrg	    break;
35275dfecf96Smrg	case NDIVIDE_ROUND:
35285dfecf96Smrg	    if (!modp || (bigi->digs[0] & 1) == 1) {
35295dfecf96Smrg		n_real cmp;
35305dfecf96Smrg
35315dfecf96Smrg		set_real_object(&cmp, div);
35325dfecf96Smrg		div_real_real(&cmp, &two);
35335dfecf96Smrg		if (dsign > 0) {
35345dfecf96Smrg		    if (rsign > 0) {
35355dfecf96Smrg			if (cmp_real_real(NIMAG(num), &cmp) >= 0)
35365dfecf96Smrg			    state = NDIVIDE_ADD;
35375dfecf96Smrg		    }
35385dfecf96Smrg		    else {
35395dfecf96Smrg			neg_real(&cmp);
35405dfecf96Smrg			if (cmp_real_real(NIMAG(num), &cmp) <= 0)
35415dfecf96Smrg			    state = NDIVIDE_SUB;
35425dfecf96Smrg		    }
35435dfecf96Smrg		}
35445dfecf96Smrg		else {
35455dfecf96Smrg		    if (rsign > 0) {
35465dfecf96Smrg			neg_real(&cmp);
35475dfecf96Smrg			if (cmp_real_real(NIMAG(num), &cmp) >= 0)
35485dfecf96Smrg			    state = NDIVIDE_SUB;
35495dfecf96Smrg		    }
35505dfecf96Smrg		    else {
35515dfecf96Smrg			if (cmp_real_real(NIMAG(num), &cmp) <= 0)
35525dfecf96Smrg			    state = NDIVIDE_ADD;
35535dfecf96Smrg		    }
35545dfecf96Smrg		}
35555dfecf96Smrg		clear_real(&cmp);
35565dfecf96Smrg	    }
35575dfecf96Smrg	    break;
35585dfecf96Smrg    }
35595dfecf96Smrg
35605dfecf96Smrg    if (state == NDIVIDE_ADD) {
35615dfecf96Smrg	add_real_real(NREAL(num), &one);
35625dfecf96Smrg	sub_real_object(NIMAG(num), div);
35635dfecf96Smrg    }
35645dfecf96Smrg    else if (state == NDIVIDE_SUB) {
35655dfecf96Smrg	sub_real_real(NREAL(num), &one);
35665dfecf96Smrg	add_real_object(NIMAG(num), div);
35675dfecf96Smrg    }
35685dfecf96Smrg
35695dfecf96Smrg    if (NRTYPE(num) == N_BIGNUM) {
35705dfecf96Smrg	if (flo) {
35715dfecf96Smrg	    double dval = bi_getd(bigi);
35725dfecf96Smrg
35735dfecf96Smrg	    mpi_clear(bigi);
35745dfecf96Smrg	    XFREE(bigi);
35755dfecf96Smrg	    NRTYPE(num) = N_FLONUM;
35765dfecf96Smrg	    NRFF(num) = dval;
35775dfecf96Smrg	}
35785dfecf96Smrg	else
35795dfecf96Smrg	    rbi_canonicalize(NREAL(num));
35805dfecf96Smrg    }
35815dfecf96Smrg    else if (flo) {
35825dfecf96Smrg	NRTYPE(num) = N_FLONUM;
35835dfecf96Smrg	NRFF(num) = (double)NRFI(num);
35845dfecf96Smrg    }
35855dfecf96Smrg}
35865dfecf96Smrg
35875dfecf96Smrg
35885dfecf96Smrg/************************************************************************
35895dfecf96Smrg * REAL COMPLEX
35905dfecf96Smrg ************************************************************************/
35915dfecf96Smrgstatic void
35925dfecf96Smrgnadd_re_cx(n_number *num, LispObj *comp)
35935dfecf96Smrg{
35945dfecf96Smrg/*
35955dfecf96Smrg	Ra+Rb Ib
35965dfecf96Smrg */
35975dfecf96Smrg    /* Ra+Rb */
35985dfecf96Smrg    add_real_object(NREAL(num), OCXR(comp));
35995dfecf96Smrg
36005dfecf96Smrg    /* Ib */
36015dfecf96Smrg    set_real_object(NIMAG(num), OCXI(comp));
36025dfecf96Smrg
36035dfecf96Smrg    num->complex = 1;
36045dfecf96Smrg
36055dfecf96Smrg    ncx_canonicalize(num);
36065dfecf96Smrg}
36075dfecf96Smrg
36085dfecf96Smrgstatic void
36095dfecf96Smrgnsub_re_cx(n_number *num, LispObj *comp)
36105dfecf96Smrg{
36115dfecf96Smrg/*
36125dfecf96Smrg	Ra-Rb -Ib
36135dfecf96Smrg */
36145dfecf96Smrg    /* Ra-Rb */
36155dfecf96Smrg    sub_real_object(NREAL(num), OCXR(comp));
36165dfecf96Smrg
36175dfecf96Smrg    /* -Ib */
36185dfecf96Smrg    NITYPE(num) = N_FIXNUM;
36195dfecf96Smrg    NIFI(num) = -1;
36205dfecf96Smrg    mul_real_object(NIMAG(num), OCXI(comp));
36215dfecf96Smrg
36225dfecf96Smrg    num->complex = 1;
36235dfecf96Smrg
36245dfecf96Smrg    ncx_canonicalize(num);
36255dfecf96Smrg}
36265dfecf96Smrg
36275dfecf96Smrgstatic void
36285dfecf96Smrgnmul_re_cx(n_number *num, LispObj *comp)
36295dfecf96Smrg{
36305dfecf96Smrg/*
36315dfecf96Smrg	Ra*Rb Ra*Ib
36325dfecf96Smrg */
36335dfecf96Smrg    /* copy before change */
36345dfecf96Smrg    set_real_real(NIMAG(num), NREAL(num));
36355dfecf96Smrg
36365dfecf96Smrg    /* Ra*Rb */
36375dfecf96Smrg    mul_real_object(NREAL(num), OCXR(comp));
36385dfecf96Smrg
36395dfecf96Smrg    /* Ra*Ib */
36405dfecf96Smrg    mul_real_object(NIMAG(num), OCXI(comp));
36415dfecf96Smrg
36425dfecf96Smrg    num->complex = 1;
36435dfecf96Smrg
36445dfecf96Smrg    ncx_canonicalize(num);
36455dfecf96Smrg}
36465dfecf96Smrg
36475dfecf96Smrgstatic void
36485dfecf96Smrgndiv_re_cx(n_number *num, LispObj *comp)
36495dfecf96Smrg{
36505dfecf96Smrg/*
36515dfecf96Smrg	Ra*Rb        -Ib*Ra
36525dfecf96Smrg	-----------  -----------
36535dfecf96Smrg	Rb*Rb+Ib*Ib  Rb*Rb+Ib*Ib
36545dfecf96Smrg */
36555dfecf96Smrg    n_real div, temp;
36565dfecf96Smrg
36575dfecf96Smrg    /* Rb*Rb */
36585dfecf96Smrg    set_real_object(&div, OCXR(comp));
36595dfecf96Smrg    mul_real_object(&div, OCXR(comp));
36605dfecf96Smrg
36615dfecf96Smrg    /* Ib*Ib */
36625dfecf96Smrg    set_real_object(&temp, OCXI(comp));
36635dfecf96Smrg    mul_real_object(&temp, OCXI(comp));
36645dfecf96Smrg
36655dfecf96Smrg    /* Rb*Rb+Ib*Ib */
36665dfecf96Smrg    add_real_real(&div, &temp);
36675dfecf96Smrg    clear_real(&temp);
36685dfecf96Smrg
36695dfecf96Smrg    /* -Ib*Ra */
36705dfecf96Smrg    NITYPE(num) = N_FIXNUM;
36715dfecf96Smrg    NIFI(num) = -1;
36725dfecf96Smrg    mul_real_object(NIMAG(num), OCXI(comp));
36735dfecf96Smrg    mul_real_real(NIMAG(num), NREAL(num));
36745dfecf96Smrg
36755dfecf96Smrg    /* Ra*Rb */
36765dfecf96Smrg    mul_real_object(NREAL(num), OCXR(comp));
36775dfecf96Smrg
36785dfecf96Smrg    div_real_real(NREAL(num), &div);
36795dfecf96Smrg    div_real_real(NIMAG(num), &div);
36805dfecf96Smrg    clear_real(&div);
36815dfecf96Smrg
36825dfecf96Smrg    num->complex = 1;
36835dfecf96Smrg
36845dfecf96Smrg    ncx_canonicalize(num);
36855dfecf96Smrg}
36865dfecf96Smrg
36875dfecf96Smrg
36885dfecf96Smrg/************************************************************************
36895dfecf96Smrg * COMPLEX REAL
36905dfecf96Smrg ************************************************************************/
36915dfecf96Smrgstatic void
36925dfecf96Smrgnadd_cx_re(n_number *num, LispObj *re)
36935dfecf96Smrg{
36945dfecf96Smrg/*
36955dfecf96Smrg	Ra+Rb Ia
36965dfecf96Smrg */
36975dfecf96Smrg    add_real_object(NREAL(num), re);
36985dfecf96Smrg
36995dfecf96Smrg    ncx_canonicalize(num);
37005dfecf96Smrg}
37015dfecf96Smrg
37025dfecf96Smrgstatic void
37035dfecf96Smrgnsub_cx_re(n_number *num, LispObj *re)
37045dfecf96Smrg{
37055dfecf96Smrg/*
37065dfecf96Smrg	Ra-Rb Ia
37075dfecf96Smrg */
37085dfecf96Smrg    sub_real_object(NREAL(num), re);
37095dfecf96Smrg
37105dfecf96Smrg    ncx_canonicalize(num);
37115dfecf96Smrg}
37125dfecf96Smrg
37135dfecf96Smrgstatic void
37145dfecf96Smrgnmul_cx_re(n_number *num, LispObj *re)
37155dfecf96Smrg{
37165dfecf96Smrg/*
37175dfecf96Smrg	Ra*Rb Ia*Rb
37185dfecf96Smrg */
37195dfecf96Smrg    mul_real_object(NREAL(num), re);
37205dfecf96Smrg    mul_real_object(NIMAG(num), re);
37215dfecf96Smrg
37225dfecf96Smrg    ncx_canonicalize(num);
37235dfecf96Smrg}
37245dfecf96Smrg
37255dfecf96Smrgstatic void
37265dfecf96Smrgndiv_cx_re(n_number *num, LispObj *re)
37275dfecf96Smrg{
37285dfecf96Smrg/*
37295dfecf96Smrg	Ra/Rb Ia/Rb
37305dfecf96Smrg */
37315dfecf96Smrg    div_real_object(NREAL(num), re);
37325dfecf96Smrg    div_real_object(NIMAG(num), re);
37335dfecf96Smrg
37345dfecf96Smrg    ncx_canonicalize(num);
37355dfecf96Smrg}
37365dfecf96Smrg
37375dfecf96Smrg
37385dfecf96Smrg/************************************************************************
37395dfecf96Smrg * COMPLEX COMPLEX
37405dfecf96Smrg ************************************************************************/
37415dfecf96Smrgstatic void
37425dfecf96Smrgnadd_cx_cx(n_number *num, LispObj *comp)
37435dfecf96Smrg{
37445dfecf96Smrg/*
37455dfecf96Smrg	Ra+Rb Ia+Ib
37465dfecf96Smrg */
37475dfecf96Smrg    add_real_object(NREAL(num), OCXR(comp));
37485dfecf96Smrg    add_real_object(NIMAG(num), OCXI(comp));
37495dfecf96Smrg
37505dfecf96Smrg    ncx_canonicalize(num);
37515dfecf96Smrg}
37525dfecf96Smrg
37535dfecf96Smrgstatic void
37545dfecf96Smrgnsub_cx_cx(n_number *num, LispObj *comp)
37555dfecf96Smrg{
37565dfecf96Smrg/*
37575dfecf96Smrg	Ra-Rb Ia-Ib
37585dfecf96Smrg */
37595dfecf96Smrg    sub_real_object(NREAL(num), OCXR(comp));
37605dfecf96Smrg    sub_real_object(NIMAG(num), OCXI(comp));
37615dfecf96Smrg
37625dfecf96Smrg    ncx_canonicalize(num);
37635dfecf96Smrg}
37645dfecf96Smrg
37655dfecf96Smrgstatic void
37665dfecf96Smrgnmul_cx_cx(n_number *num, LispObj *comp)
37675dfecf96Smrg{
37685dfecf96Smrg/*
37695dfecf96Smrg	Ra*Rb-Ia*Ib Ra*Ib+Ia*Rb
37705dfecf96Smrg */
37715dfecf96Smrg    n_real IaIb, RaIb;
37725dfecf96Smrg
37735dfecf96Smrg    set_real_real(&IaIb, NIMAG(num));
37745dfecf96Smrg    mul_real_object(&IaIb, OCXI(comp));
37755dfecf96Smrg
37765dfecf96Smrg    set_real_real(&RaIb, NREAL(num));
37775dfecf96Smrg    mul_real_object(&RaIb, OCXI(comp));
37785dfecf96Smrg
37795dfecf96Smrg    /* Ra*Rb-Ia*Ib */
37805dfecf96Smrg    mul_real_object(NREAL(num), OCXR(comp));
37815dfecf96Smrg    sub_real_real(NREAL(num), &IaIb);
37825dfecf96Smrg    clear_real(&IaIb);
37835dfecf96Smrg
37845dfecf96Smrg    /* Ra*Ib+Ia*Rb */
37855dfecf96Smrg    mul_real_object(NIMAG(num), OCXR(comp));
37865dfecf96Smrg    add_real_real(NIMAG(num), &RaIb);
37875dfecf96Smrg    clear_real(&RaIb);
37885dfecf96Smrg
37895dfecf96Smrg    ncx_canonicalize(num);
37905dfecf96Smrg}
37915dfecf96Smrg
37925dfecf96Smrgstatic void
37935dfecf96Smrgndiv_cx_cx(n_number *num, LispObj *comp)
37945dfecf96Smrg{
37955dfecf96Smrg/*
37965dfecf96Smrg	Ra*Rb+Ia*Ib  Ia*Rb-Ib*Ra
37975dfecf96Smrg	-----------  -----------
37985dfecf96Smrg	Rb*Rb+Ib*Ib  Rb*Rb+Ib*Ib
37995dfecf96Smrg */
38005dfecf96Smrg    n_real temp1, temp2;
38015dfecf96Smrg
38025dfecf96Smrg    /* IaIb */
38035dfecf96Smrg    set_real_real(&temp1, NIMAG(num));
38045dfecf96Smrg    mul_real_object(&temp1, OCXI(comp));
38055dfecf96Smrg
38065dfecf96Smrg    /* IbRa */
38075dfecf96Smrg    set_real_real(&temp2, NREAL(num));
38085dfecf96Smrg    mul_real_object(&temp2, OCXI(comp));
38095dfecf96Smrg
38105dfecf96Smrg    /* Ra*Rb+Ia*Ib */
38115dfecf96Smrg    mul_real_object(NREAL(num), OCXR(comp));
38125dfecf96Smrg    add_real_real(NREAL(num), &temp1);
38135dfecf96Smrg    clear_real(&temp1);
38145dfecf96Smrg
38155dfecf96Smrg    /* Ia*Rb-Ib*Ra */
38165dfecf96Smrg    mul_real_object(NIMAG(num), OCXR(comp));
38175dfecf96Smrg    sub_real_real(NIMAG(num), &temp2);
38185dfecf96Smrg    clear_real(&temp2);
38195dfecf96Smrg
38205dfecf96Smrg
38215dfecf96Smrg    /* Rb*Rb */
38225dfecf96Smrg    set_real_object(&temp1, OCXR(comp));
38235dfecf96Smrg    mul_real_object(&temp1, OCXR(comp));
38245dfecf96Smrg
38255dfecf96Smrg    /* Ib*Ib */
38265dfecf96Smrg    set_real_object(&temp2, OCXI(comp));
38275dfecf96Smrg    mul_real_object(&temp2, OCXI(comp));
38285dfecf96Smrg
38295dfecf96Smrg    /* Rb*Rb+Ib*Ib */
38305dfecf96Smrg    add_real_real(&temp1, &temp2);
38315dfecf96Smrg    clear_real(&temp2);
38325dfecf96Smrg
38335dfecf96Smrg    div_real_real(NREAL(num), &temp1);
38345dfecf96Smrg    div_real_real(NIMAG(num), &temp1);
38355dfecf96Smrg    clear_real(&temp1);
38365dfecf96Smrg
38375dfecf96Smrg    ncx_canonicalize(num);
38385dfecf96Smrg}
38395dfecf96Smrg
38405dfecf96Smrgstatic int
38415dfecf96Smrgcmp_cx_cx(LispObj *op1, LispObj *op2)
38425dfecf96Smrg{
38435dfecf96Smrg    int cmp;
38445dfecf96Smrg
38455dfecf96Smrg    cmp = cmp_object_object(OCXR(op1), OCXR(op2), 1);
38465dfecf96Smrg    if (cmp == 0)
38475dfecf96Smrg	cmp = cmp_object_object(OCXI(op1), OCXI(op2), 1);
38485dfecf96Smrg
38495dfecf96Smrg    return (cmp);
38505dfecf96Smrg}
38515dfecf96Smrg
38525dfecf96Smrg
38535dfecf96Smrg/************************************************************************
38545dfecf96Smrg * FLONUM FLONUM
38555dfecf96Smrg ************************************************************************/
38565dfecf96Smrgstatic void
38575dfecf96Smrgradd_flonum(n_real *real, double op1, double op2)
38585dfecf96Smrg{
38595dfecf96Smrg    double value = op1 + op2;
38605dfecf96Smrg
38615dfecf96Smrg    if (!finite(value))
38625dfecf96Smrg	fatal_error(FLOATING_POINT_OVERFLOW);
38635dfecf96Smrg    switch (RTYPE(real)) {
38645dfecf96Smrg	case N_FIXNUM:
38655dfecf96Smrg	case N_FIXRATIO:
38665dfecf96Smrg	    RTYPE(real) = N_FLONUM;
38675dfecf96Smrg	    break;
38685dfecf96Smrg	case N_BIGNUM:
38695dfecf96Smrg	    RCLEAR_BI(real);
38705dfecf96Smrg	    RTYPE(real) = N_FLONUM;
38715dfecf96Smrg	    break;
38725dfecf96Smrg	case N_BIGRATIO:
38735dfecf96Smrg	    RCLEAR_BR(real);
38745dfecf96Smrg	    RTYPE(real) = N_FLONUM;
38755dfecf96Smrg	    break;
38765dfecf96Smrg    }
38775dfecf96Smrg    RFF(real) = value;
38785dfecf96Smrg}
38795dfecf96Smrg
38805dfecf96Smrgstatic void
38815dfecf96Smrgrsub_flonum(n_real *real, double op1, double op2)
38825dfecf96Smrg{
38835dfecf96Smrg    double value = op1 - op2;
38845dfecf96Smrg
38855dfecf96Smrg    if (!finite(value))
38865dfecf96Smrg	fatal_error(FLOATING_POINT_OVERFLOW);
38875dfecf96Smrg    switch (RTYPE(real)) {
38885dfecf96Smrg	case N_FIXNUM:
38895dfecf96Smrg	case N_FIXRATIO:
38905dfecf96Smrg	    RTYPE(real) = N_FLONUM;
38915dfecf96Smrg	    break;
38925dfecf96Smrg	case N_BIGNUM:
38935dfecf96Smrg	    RCLEAR_BI(real);
38945dfecf96Smrg	    RTYPE(real) = N_FLONUM;
38955dfecf96Smrg	    break;
38965dfecf96Smrg	case N_BIGRATIO:
38975dfecf96Smrg	    RCLEAR_BR(real);
38985dfecf96Smrg	    RTYPE(real) = N_FLONUM;
38995dfecf96Smrg	    break;
39005dfecf96Smrg    }
39015dfecf96Smrg    RFF(real) = value;
39025dfecf96Smrg}
39035dfecf96Smrg
39045dfecf96Smrgstatic void
39055dfecf96Smrgrmul_flonum(n_real *real, double op1, double op2)
39065dfecf96Smrg{
39075dfecf96Smrg    double value = op1 * op2;
39085dfecf96Smrg
39095dfecf96Smrg    if (!finite(value))
39105dfecf96Smrg	fatal_error(FLOATING_POINT_OVERFLOW);
39115dfecf96Smrg    switch (RTYPE(real)) {
39125dfecf96Smrg	case N_FIXNUM:
39135dfecf96Smrg	case N_FIXRATIO:
39145dfecf96Smrg	    RTYPE(real) = N_FLONUM;
39155dfecf96Smrg	    break;
39165dfecf96Smrg	case N_BIGNUM:
39175dfecf96Smrg	    RCLEAR_BI(real);
39185dfecf96Smrg	    RTYPE(real) = N_FLONUM;
39195dfecf96Smrg	    break;
39205dfecf96Smrg	case N_BIGRATIO:
39215dfecf96Smrg	    RCLEAR_BR(real);
39225dfecf96Smrg	    RTYPE(real) = N_FLONUM;
39235dfecf96Smrg	    break;
39245dfecf96Smrg    }
39255dfecf96Smrg    RFF(real) = value;
39265dfecf96Smrg}
39275dfecf96Smrg
39285dfecf96Smrgstatic void
39295dfecf96Smrgrdiv_flonum(n_real *real, double op1, double op2)
39305dfecf96Smrg{
39315dfecf96Smrg    double value;
39325dfecf96Smrg
39335dfecf96Smrg    if (op2 == 0.0)
39345dfecf96Smrg	fatal_error(DIVIDE_BY_ZERO);
39355dfecf96Smrg    value = op1 / op2;
39365dfecf96Smrg    if (!finite(value))
39375dfecf96Smrg	fatal_error(FLOATING_POINT_OVERFLOW);
39385dfecf96Smrg    switch (RTYPE(real)) {
39395dfecf96Smrg	case N_FIXNUM:
39405dfecf96Smrg	case N_FIXRATIO:
39415dfecf96Smrg	    RTYPE(real) = N_FLONUM;
39425dfecf96Smrg	    break;
39435dfecf96Smrg	case N_BIGNUM:
39445dfecf96Smrg	    RCLEAR_BI(real);
39455dfecf96Smrg	    RTYPE(real) = N_FLONUM;
39465dfecf96Smrg	    break;
39475dfecf96Smrg	case N_BIGRATIO:
39485dfecf96Smrg	    RCLEAR_BR(real);
39495dfecf96Smrg	    RTYPE(real) = N_FLONUM;
39505dfecf96Smrg	    break;
39515dfecf96Smrg    }
39525dfecf96Smrg    RFF(real) = value;
39535dfecf96Smrg}
39545dfecf96Smrg
39555dfecf96Smrgstatic int
39565dfecf96Smrgcmp_flonum(double op1, double op2)
39575dfecf96Smrg{
39585dfecf96Smrg    double value = op1 - op2;
39595dfecf96Smrg
39605dfecf96Smrg    if (!finite(value))
39615dfecf96Smrg	fatal_error(FLOATING_POINT_OVERFLOW);
39625dfecf96Smrg
39635dfecf96Smrg    return (value > 0.0 ? 1 : value < 0.0 ? -1 : 0);
39645dfecf96Smrg}
39655dfecf96Smrg
39665dfecf96Smrg
39675dfecf96Smrg/************************************************************************
39685dfecf96Smrg * FIXNUM FIXNUM
39695dfecf96Smrg ************************************************************************/
39705dfecf96Smrgstatic void
39715dfecf96Smrgrop_fi_fi_bi(n_real *real, long fi, int op)
39725dfecf96Smrg{
39735dfecf96Smrg    mpi *bigi = XALLOC(mpi);
39745dfecf96Smrg
39755dfecf96Smrg    mpi_init(bigi);
39765dfecf96Smrg    mpi_seti(bigi, RFI(real));
39775dfecf96Smrg    if (op == NOP_ADD)
39785dfecf96Smrg	mpi_addi(bigi, bigi, fi);
39795dfecf96Smrg    else if (op == NOP_SUB)
39805dfecf96Smrg	mpi_subi(bigi, bigi, fi);
39815dfecf96Smrg    else
39825dfecf96Smrg	mpi_muli(bigi, bigi, fi);
39835dfecf96Smrg    RBI(real) = bigi;
39845dfecf96Smrg    RTYPE(real) = N_BIGNUM;
39855dfecf96Smrg}
39865dfecf96Smrg
39875dfecf96Smrgstatic INLINE void
39885dfecf96Smrgradd_fi_fi(n_real *real, long fi)
39895dfecf96Smrg{
39905dfecf96Smrg    if (!fi_fi_add_overflow(RFI(real), fi))
39915dfecf96Smrg	RFI(real) += fi;
39925dfecf96Smrg    else
39935dfecf96Smrg	rop_fi_fi_bi(real, fi, NOP_ADD);
39945dfecf96Smrg}
39955dfecf96Smrg
39965dfecf96Smrgstatic INLINE void
39975dfecf96Smrgrsub_fi_fi(n_real *real, long fi)
39985dfecf96Smrg{
39995dfecf96Smrg    if (!fi_fi_sub_overflow(RFI(real), fi))
40005dfecf96Smrg	RFI(real) -= fi;
40015dfecf96Smrg    else
40025dfecf96Smrg	rop_fi_fi_bi(real, fi, NOP_SUB);
40035dfecf96Smrg}
40045dfecf96Smrg
40055dfecf96Smrgstatic INLINE void
40065dfecf96Smrgrmul_fi_fi(n_real *real, long fi)
40075dfecf96Smrg{
40085dfecf96Smrg    if (!fi_fi_mul_overflow(RFI(real), fi))
40095dfecf96Smrg	RFI(real) *= fi;
40105dfecf96Smrg    else
40115dfecf96Smrg	rop_fi_fi_bi(real, fi, NOP_MUL);
40125dfecf96Smrg}
40135dfecf96Smrg
40145dfecf96Smrgstatic INLINE void
40155dfecf96Smrgrdiv_fi_fi(n_real *real, long fi)
40165dfecf96Smrg{
40175dfecf96Smrg    RTYPE(real) = N_FIXRATIO;
40185dfecf96Smrg    RFRN(real) = RFI(real);
40195dfecf96Smrg    RFRD(real) = fi;
40205dfecf96Smrg    rfr_canonicalize(real);
40215dfecf96Smrg}
40225dfecf96Smrg
40235dfecf96Smrgstatic INLINE int
40245dfecf96Smrgcmp_fi_fi(long op1, long op2)
40255dfecf96Smrg{
40265dfecf96Smrg    if (op1 > op2)
40275dfecf96Smrg	return (1);
40285dfecf96Smrg    else if (op1 < op2)
40295dfecf96Smrg	return (-1);
40305dfecf96Smrg
40315dfecf96Smrg    return (0);
40325dfecf96Smrg}
40335dfecf96Smrg
40345dfecf96Smrg
40355dfecf96Smrg/************************************************************************
40365dfecf96Smrg * FIXNUM BIGNUM
40375dfecf96Smrg ************************************************************************/
40385dfecf96Smrgstatic void
40395dfecf96Smrgrop_fi_bi_xi(n_real *real, mpi *bi, int nop)
40405dfecf96Smrg{
40415dfecf96Smrg    mpi *bigi = XALLOC(mpi);
40425dfecf96Smrg
40435dfecf96Smrg    mpi_init(bigi);
40445dfecf96Smrg    mpi_seti(bigi, RFI(real));
40455dfecf96Smrg    if (nop == NOP_ADD)
40465dfecf96Smrg	mpi_add(bigi, bigi, bi);
40475dfecf96Smrg    else if (nop == NOP_SUB)
40485dfecf96Smrg	mpi_sub(bigi, bigi, bi);
40495dfecf96Smrg    else
40505dfecf96Smrg	mpi_mul(bigi, bigi, bi);
40515dfecf96Smrg
40525dfecf96Smrg    if (mpi_fiti(bigi)) {
40535dfecf96Smrg	RFI(real) = mpi_geti(bigi);
40545dfecf96Smrg	mpi_clear(bigi);
40555dfecf96Smrg	XFREE(bigi);
40565dfecf96Smrg    }
40575dfecf96Smrg    else {
40585dfecf96Smrg	RBI(real) = bigi;
40595dfecf96Smrg	RTYPE(real) = N_BIGNUM;
40605dfecf96Smrg    }
40615dfecf96Smrg}
40625dfecf96Smrg
40635dfecf96Smrgstatic INLINE void
40645dfecf96Smrgradd_fi_bi(n_real *real, mpi *bi)
40655dfecf96Smrg{
40665dfecf96Smrg    rop_fi_bi_xi(real, bi, NOP_ADD);
40675dfecf96Smrg}
40685dfecf96Smrg
40695dfecf96Smrgstatic INLINE void
40705dfecf96Smrgrsub_fi_bi(n_real *real, mpi *bi)
40715dfecf96Smrg{
40725dfecf96Smrg    rop_fi_bi_xi(real, bi, NOP_SUB);
40735dfecf96Smrg}
40745dfecf96Smrg
40755dfecf96Smrgstatic INLINE void
40765dfecf96Smrgrmul_fi_bi(n_real *real, mpi *bi)
40775dfecf96Smrg{
40785dfecf96Smrg    rop_fi_bi_xi(real, bi, NOP_MUL);
40795dfecf96Smrg}
40805dfecf96Smrg
40815dfecf96Smrgstatic void
40825dfecf96Smrgrdiv_fi_bi(n_real *real, mpi *bi)
40835dfecf96Smrg{
40845dfecf96Smrg    mpr *bigr;
40855dfecf96Smrg
40865dfecf96Smrg    if (mpi_cmpi(bi, 0) == 0)
40875dfecf96Smrg	fatal_error(DIVIDE_BY_ZERO);
40885dfecf96Smrg
40895dfecf96Smrg    bigr = XALLOC(mpr);
40905dfecf96Smrg    mpr_init(bigr);
40915dfecf96Smrg    mpi_seti(mpr_num(bigr), RFI(real));
40925dfecf96Smrg    mpi_set(mpr_den(bigr), bi);
40935dfecf96Smrg    RBR(real) = bigr;
40945dfecf96Smrg    RTYPE(real) = N_BIGRATIO;
40955dfecf96Smrg    rbr_canonicalize(real);
40965dfecf96Smrg}
40975dfecf96Smrg
40985dfecf96Smrgstatic INLINE int
40995dfecf96Smrgcmp_fi_bi(long fixnum, mpi *bignum)
41005dfecf96Smrg{
41015dfecf96Smrg    return (-mpi_cmpi(bignum, fixnum));
41025dfecf96Smrg}
41035dfecf96Smrg
41045dfecf96Smrg
41055dfecf96Smrg/************************************************************************
41065dfecf96Smrg * FIXNUM FIXRATIO
41075dfecf96Smrg ************************************************************************/
41085dfecf96Smrgstatic void
41095dfecf96Smrgrop_fi_fr_as_xr(n_real *real, long num, long den, int nop)
41105dfecf96Smrg{
41115dfecf96Smrg    int fit;
41125dfecf96Smrg    long value = 0, op = RFI(real);
41135dfecf96Smrg
41145dfecf96Smrg    fit = !fi_fi_mul_overflow(op, den);
41155dfecf96Smrg    if (fit) {
41165dfecf96Smrg	value = op * den;
41175dfecf96Smrg	if (nop == NOP_ADD)
41185dfecf96Smrg	    fit = !fi_fi_add_overflow(value, num);
41195dfecf96Smrg	else
41205dfecf96Smrg	    fit = !fi_fi_sub_overflow(value, num);
41215dfecf96Smrg    }
41225dfecf96Smrg    if (fit) {
41235dfecf96Smrg	if (nop == NOP_ADD)
41245dfecf96Smrg	    RFRN(real) = value + num;
41255dfecf96Smrg	else
41265dfecf96Smrg	    RFRN(real) = value - num;
41275dfecf96Smrg	RFRD(real) = den;
41285dfecf96Smrg	RTYPE(real) = N_FIXRATIO;
41295dfecf96Smrg	rfr_canonicalize(real);
41305dfecf96Smrg    }
41315dfecf96Smrg    else {
41325dfecf96Smrg	mpi iop;
41335dfecf96Smrg	mpr *bigr = XALLOC(mpr);
41345dfecf96Smrg
41355dfecf96Smrg	mpi_init(&iop);
41365dfecf96Smrg	mpi_seti(&iop, op);
41375dfecf96Smrg	mpi_muli(&iop, &iop, den);
41385dfecf96Smrg
41395dfecf96Smrg	mpr_init(bigr);
41405dfecf96Smrg	mpr_seti(bigr, num, den);
41415dfecf96Smrg	if (nop == NOP_ADD)
41425dfecf96Smrg	    mpi_add(mpr_num(bigr), &iop, mpr_num(bigr));
41435dfecf96Smrg	else
41445dfecf96Smrg	    mpi_sub(mpr_num(bigr), &iop, mpr_num(bigr));
41455dfecf96Smrg	mpi_clear(&iop);
41465dfecf96Smrg	RBR(real) = bigr;
41475dfecf96Smrg	RTYPE(real) = N_BIGRATIO;
41485dfecf96Smrg	rbr_canonicalize(real);
41495dfecf96Smrg    }
41505dfecf96Smrg}
41515dfecf96Smrg
41525dfecf96Smrgstatic void
41535dfecf96Smrgrop_fi_fr_md_xr(n_real *real, long num, long den, int nop)
41545dfecf96Smrg{
41555dfecf96Smrg    int fit;
41565dfecf96Smrg    long op = RFI(real);
41575dfecf96Smrg
41585dfecf96Smrg    if (nop == NOP_MUL)
41595dfecf96Smrg	fit = !fi_fi_mul_overflow(op, num);
41605dfecf96Smrg    else
41615dfecf96Smrg	fit = !fi_fi_mul_overflow(op, den);
41625dfecf96Smrg    if (fit) {
41635dfecf96Smrg	if (nop == NOP_MUL) {
41645dfecf96Smrg	    RFRN(real) = op * num;
41655dfecf96Smrg	    RFRD(real) = den;
41665dfecf96Smrg	}
41675dfecf96Smrg	else {
41685dfecf96Smrg	    RFRN(real) = op * den;
41695dfecf96Smrg	    RFRD(real) = num;
41705dfecf96Smrg	}
41715dfecf96Smrg	RTYPE(real) = N_FIXRATIO;
41725dfecf96Smrg	rfr_canonicalize(real);
41735dfecf96Smrg    }
41745dfecf96Smrg    else {
41755dfecf96Smrg	mpi iop;
41765dfecf96Smrg	mpr *bigr = XALLOC(mpr);
41775dfecf96Smrg
41785dfecf96Smrg	mpi_init(&iop);
41795dfecf96Smrg	mpi_seti(&iop, op);
41805dfecf96Smrg
41815dfecf96Smrg	mpr_init(bigr);
41825dfecf96Smrg	if (nop == NOP_MUL)
41835dfecf96Smrg	    mpr_seti(bigr, num, den);
41845dfecf96Smrg	else
41855dfecf96Smrg	    mpr_seti(bigr, den, num);
41865dfecf96Smrg	mpi_mul(mpr_num(bigr), mpr_num(bigr), &iop);
41875dfecf96Smrg	mpi_clear(&iop);
41885dfecf96Smrg	RBR(real) = bigr;
41895dfecf96Smrg	RTYPE(real) = N_BIGRATIO;
41905dfecf96Smrg	rbr_canonicalize(real);
41915dfecf96Smrg    }
41925dfecf96Smrg}
41935dfecf96Smrg
41945dfecf96Smrgstatic INLINE void
41955dfecf96Smrgradd_fi_fr(n_real *real, long num, long den)
41965dfecf96Smrg{
41975dfecf96Smrg    rop_fi_fr_as_xr(real, num, den, NOP_ADD);
41985dfecf96Smrg}
41995dfecf96Smrg
42005dfecf96Smrgstatic INLINE void
42015dfecf96Smrgrsub_fi_fr(n_real *real, long num, long den)
42025dfecf96Smrg{
42035dfecf96Smrg    rop_fi_fr_as_xr(real, num, den, NOP_SUB);
42045dfecf96Smrg}
42055dfecf96Smrg
42065dfecf96Smrgstatic INLINE void
42075dfecf96Smrgrmul_fi_fr(n_real *real, long num, long den)
42085dfecf96Smrg{
42095dfecf96Smrg    rop_fi_fr_md_xr(real, num, den, NOP_MUL);
42105dfecf96Smrg}
42115dfecf96Smrg
42125dfecf96Smrgstatic INLINE void
42135dfecf96Smrgrdiv_fi_fr(n_real *real, long num, long den)
42145dfecf96Smrg{
42155dfecf96Smrg    rop_fi_fr_md_xr(real, num, den, NOP_DIV);
42165dfecf96Smrg}
42175dfecf96Smrg
42185dfecf96Smrgstatic INLINE int
42195dfecf96Smrgcmp_fi_fr(long fi, long num, long den)
42205dfecf96Smrg{
42215dfecf96Smrg    return (cmp_flonum((double)fi, (double)num / (double)den));
42225dfecf96Smrg}
42235dfecf96Smrg
42245dfecf96Smrg
42255dfecf96Smrg/************************************************************************
42265dfecf96Smrg * FIXNUM BIGRATIO
42275dfecf96Smrg ************************************************************************/
42285dfecf96Smrgstatic void
42295dfecf96Smrgrop_fi_br_as_xr(n_real *real, mpr *ratio, int nop)
42305dfecf96Smrg{
42315dfecf96Smrg    mpi iop;
42325dfecf96Smrg    mpr *bigr = XALLOC(mpr);
42335dfecf96Smrg
42345dfecf96Smrg    mpi_init(&iop);
42355dfecf96Smrg    mpi_seti(&iop, RFI(real));
42365dfecf96Smrg
42375dfecf96Smrg    mpr_init(bigr);
42385dfecf96Smrg    mpr_set(bigr, ratio);
42395dfecf96Smrg
42405dfecf96Smrg    mpi_mul(&iop, &iop, mpr_den(ratio));
42415dfecf96Smrg    if (nop == NOP_ADD)
42425dfecf96Smrg	mpi_add(mpr_num(bigr), &iop, mpr_num(bigr));
42435dfecf96Smrg    else
42445dfecf96Smrg	mpi_sub(mpr_num(bigr), &iop, mpr_num(bigr));
42455dfecf96Smrg
42465dfecf96Smrg    mpi_clear(&iop);
42475dfecf96Smrg    RBR(real) = bigr;
42485dfecf96Smrg    RTYPE(real) = N_BIGRATIO;
42495dfecf96Smrg    rbr_canonicalize(real);
42505dfecf96Smrg}
42515dfecf96Smrg
42525dfecf96Smrgstatic void
42535dfecf96Smrgrop_fi_br_md_xr(n_real *real, mpr *ratio, int nop)
42545dfecf96Smrg{
42555dfecf96Smrg    mpi iop;
42565dfecf96Smrg    mpr *bigr = XALLOC(mpr);
42575dfecf96Smrg
42585dfecf96Smrg    mpi_init(&iop);
42595dfecf96Smrg    mpi_seti(&iop, RFI(real));
42605dfecf96Smrg
42615dfecf96Smrg    mpr_init(bigr);
42625dfecf96Smrg    if (nop == NOP_MUL)
42635dfecf96Smrg	mpr_set(bigr, ratio);
42645dfecf96Smrg    else
42655dfecf96Smrg	mpr_inv(bigr, ratio);
42665dfecf96Smrg
42675dfecf96Smrg    mpi_mul(mpr_num(bigr), &iop, mpr_num(bigr));
42685dfecf96Smrg
42695dfecf96Smrg    mpi_clear(&iop);
42705dfecf96Smrg    RBR(real) = bigr;
42715dfecf96Smrg    RTYPE(real) = N_BIGRATIO;
42725dfecf96Smrg    rbr_canonicalize(real);
42735dfecf96Smrg}
42745dfecf96Smrg
42755dfecf96Smrgstatic INLINE void
42765dfecf96Smrgradd_fi_br(n_real *real, mpr *ratio)
42775dfecf96Smrg{
42785dfecf96Smrg    rop_fi_br_as_xr(real, ratio, NOP_ADD);
42795dfecf96Smrg}
42805dfecf96Smrg
42815dfecf96Smrgstatic INLINE void
42825dfecf96Smrgrsub_fi_br(n_real *real, mpr *ratio)
42835dfecf96Smrg{
42845dfecf96Smrg    rop_fi_br_as_xr(real, ratio, NOP_SUB);
42855dfecf96Smrg}
42865dfecf96Smrg
42875dfecf96Smrgstatic INLINE void
42885dfecf96Smrgrmul_fi_br(n_real *real, mpr *ratio)
42895dfecf96Smrg{
42905dfecf96Smrg    rop_fi_br_md_xr(real, ratio, NOP_MUL);
42915dfecf96Smrg}
42925dfecf96Smrg
42935dfecf96Smrgstatic INLINE void
42945dfecf96Smrgrdiv_fi_br(n_real *real, mpr *ratio)
42955dfecf96Smrg{
42965dfecf96Smrg    rop_fi_br_md_xr(real, ratio, NOP_DIV);
42975dfecf96Smrg}
42985dfecf96Smrg
42995dfecf96Smrgstatic INLINE int
43005dfecf96Smrgcmp_fi_br(long op1, mpr *op2)
43015dfecf96Smrg{
43025dfecf96Smrg    return (-mpr_cmpi(op2, op1));
43035dfecf96Smrg}
43045dfecf96Smrg
43055dfecf96Smrg
43065dfecf96Smrg/************************************************************************
43075dfecf96Smrg * BIGNUM FIXNUM
43085dfecf96Smrg ************************************************************************/
43095dfecf96Smrgstatic INLINE void
43105dfecf96Smrgradd_bi_fi(n_real *real, long fi)
43115dfecf96Smrg{
43125dfecf96Smrg    mpi_addi(RBI(real), RBI(real), fi);
43135dfecf96Smrg    rbi_canonicalize(real);
43145dfecf96Smrg}
43155dfecf96Smrg
43165dfecf96Smrgstatic INLINE void
43175dfecf96Smrgrsub_bi_fi(n_real *real, long fi)
43185dfecf96Smrg{
43195dfecf96Smrg    mpi_subi(RBI(real), RBI(real), fi);
43205dfecf96Smrg    rbi_canonicalize(real);
43215dfecf96Smrg}
43225dfecf96Smrg
43235dfecf96Smrgstatic INLINE void
43245dfecf96Smrgrmul_bi_fi(n_real *real, long fi)
43255dfecf96Smrg{
43265dfecf96Smrg    mpi_muli(RBI(real), RBI(real), fi);
43275dfecf96Smrg    rbi_canonicalize(real);
43285dfecf96Smrg}
43295dfecf96Smrg
43305dfecf96Smrgstatic void
43315dfecf96Smrgrdiv_bi_fi(n_real *real, long fi)
43325dfecf96Smrg{
43335dfecf96Smrg    mpr *bigr;
43345dfecf96Smrg
43355dfecf96Smrg    if (RFI(real) == 0)
43365dfecf96Smrg	fatal_error(DIVIDE_BY_ZERO);
43375dfecf96Smrg
43385dfecf96Smrg    bigr = XALLOC(mpr);
43395dfecf96Smrg    mpr_init(bigr);
43405dfecf96Smrg    mpi_set(mpr_num(bigr), RBI(real));
43415dfecf96Smrg    mpi_seti(mpr_den(bigr), fi);
43425dfecf96Smrg    RCLEAR_BI(real);
43435dfecf96Smrg    RBR(real) = bigr;
43445dfecf96Smrg    RTYPE(real) = N_BIGRATIO;
43455dfecf96Smrg    rbr_canonicalize(real);
43465dfecf96Smrg}
43475dfecf96Smrg
43485dfecf96Smrgstatic INLINE int
43495dfecf96Smrgcmp_bi_fi(mpi *bignum, long fi)
43505dfecf96Smrg{
43515dfecf96Smrg    return (mpi_cmpi(bignum, fi));
43525dfecf96Smrg}
43535dfecf96Smrg
43545dfecf96Smrg
43555dfecf96Smrg/************************************************************************
43565dfecf96Smrg * BIGNUM BIGNUM
43575dfecf96Smrg ************************************************************************/
43585dfecf96Smrgstatic INLINE void
43595dfecf96Smrgradd_bi_bi(n_real *real, mpi *bignum)
43605dfecf96Smrg{
43615dfecf96Smrg    mpi_add(RBI(real), RBI(real), bignum);
43625dfecf96Smrg    rbi_canonicalize(real);
43635dfecf96Smrg}
43645dfecf96Smrg
43655dfecf96Smrgstatic INLINE void
43665dfecf96Smrgrsub_bi_bi(n_real *real, mpi *bignum)
43675dfecf96Smrg{
43685dfecf96Smrg    mpi_sub(RBI(real), RBI(real), bignum);
43695dfecf96Smrg    rbi_canonicalize(real);
43705dfecf96Smrg}
43715dfecf96Smrg
43725dfecf96Smrgstatic INLINE void
43735dfecf96Smrgrmul_bi_bi(n_real *real, mpi *bignum)
43745dfecf96Smrg{
43755dfecf96Smrg    mpi_mul(RBI(real), RBI(real), bignum);
43765dfecf96Smrg    rbi_canonicalize(real);
43775dfecf96Smrg}
43785dfecf96Smrg
43795dfecf96Smrgstatic void
43805dfecf96Smrgrdiv_bi_bi(n_real *real, mpi *bignum)
43815dfecf96Smrg{
43825dfecf96Smrg    mpr *bigr;
43835dfecf96Smrg
43845dfecf96Smrg    if (mpi_cmpi(bignum, 0) == 0)
43855dfecf96Smrg	fatal_error(DIVIDE_BY_ZERO);
43865dfecf96Smrg
43875dfecf96Smrg    bigr = XALLOC(mpr);
43885dfecf96Smrg    mpr_init(bigr);
43895dfecf96Smrg    mpi_set(mpr_num(bigr), RBI(real));
43905dfecf96Smrg    mpi_set(mpr_den(bigr), bignum);
43915dfecf96Smrg    RCLEAR_BI(real);
43925dfecf96Smrg    RBR(real) = bigr;
43935dfecf96Smrg    RTYPE(real) = N_BIGRATIO;
43945dfecf96Smrg    rbr_canonicalize(real);
43955dfecf96Smrg}
43965dfecf96Smrg
43975dfecf96Smrgstatic INLINE int
43985dfecf96Smrgcmp_bi_bi(mpi *op1, mpi *op2)
43995dfecf96Smrg{
44005dfecf96Smrg    return (mpi_cmp(op1, op2));
44015dfecf96Smrg}
44025dfecf96Smrg
44035dfecf96Smrg
44045dfecf96Smrg/************************************************************************
44055dfecf96Smrg * BIGNUM FIXRATIO
44065dfecf96Smrg ************************************************************************/
44075dfecf96Smrgstatic void
44085dfecf96Smrgrop_bi_fr_as_xr(n_real *real, long num, long den, int nop)
44095dfecf96Smrg{
44105dfecf96Smrg    mpi iop;
44115dfecf96Smrg    mpr *bigr = XALLOC(mpr);
44125dfecf96Smrg
44135dfecf96Smrg    mpi_init(&iop);
44145dfecf96Smrg    mpi_set(&iop, RBI(real));
44155dfecf96Smrg    mpi_muli(&iop, &iop, den);
44165dfecf96Smrg
44175dfecf96Smrg    mpr_init(bigr);
44185dfecf96Smrg    mpr_seti(bigr, num, den);
44195dfecf96Smrg
44205dfecf96Smrg    if (nop == NOP_ADD)
44215dfecf96Smrg	mpi_add(mpr_num(bigr), &iop, mpr_num(bigr));
44225dfecf96Smrg    else
44235dfecf96Smrg	mpi_sub(mpr_num(bigr), &iop, mpr_num(bigr));
44245dfecf96Smrg    mpi_clear(&iop);
44255dfecf96Smrg
44265dfecf96Smrg    RCLEAR_BI(real);
44275dfecf96Smrg    RBR(real) = bigr;
44285dfecf96Smrg    RTYPE(real) = N_BIGRATIO;
44295dfecf96Smrg    rbr_canonicalize(real);
44305dfecf96Smrg}
44315dfecf96Smrg
44325dfecf96Smrgstatic INLINE void
44335dfecf96Smrgrop_bi_fr_md_xr(n_real *real, long num, long den, int nop)
44345dfecf96Smrg{
44355dfecf96Smrg    mpr *bigr = XALLOC(mpr);
44365dfecf96Smrg
44375dfecf96Smrg    mpr_init(bigr);
44385dfecf96Smrg
44395dfecf96Smrg    mpr_seti(bigr, num, den);
44405dfecf96Smrg
44415dfecf96Smrg    if (nop == NOP_MUL)
44425dfecf96Smrg	mpi_mul(mpr_num(bigr), RBI(real), mpr_num(bigr));
44435dfecf96Smrg    else {
44445dfecf96Smrg	mpi_mul(mpr_den(bigr), RBI(real), mpr_den(bigr));
44455dfecf96Smrg	mpr_inv(bigr, bigr);
44465dfecf96Smrg    }
44475dfecf96Smrg
44485dfecf96Smrg    RCLEAR_BI(real);
44495dfecf96Smrg    RBR(real) = bigr;
44505dfecf96Smrg    RTYPE(real) = N_BIGRATIO;
44515dfecf96Smrg    rbr_canonicalize(real);
44525dfecf96Smrg}
44535dfecf96Smrg
44545dfecf96Smrgstatic INLINE void
44555dfecf96Smrgradd_bi_fr(n_real *real, long num, long den)
44565dfecf96Smrg{
44575dfecf96Smrg    rop_bi_fr_as_xr(real, num, den, NOP_ADD);
44585dfecf96Smrg}
44595dfecf96Smrg
44605dfecf96Smrgstatic INLINE void
44615dfecf96Smrgrsub_bi_fr(n_real *real, long num, long den)
44625dfecf96Smrg{
44635dfecf96Smrg    rop_bi_fr_as_xr(real, num, den, NOP_SUB);
44645dfecf96Smrg}
44655dfecf96Smrg
44665dfecf96Smrgstatic INLINE void
44675dfecf96Smrgrmul_bi_fr(n_real *real, long num, long den)
44685dfecf96Smrg{
44695dfecf96Smrg    rop_bi_fr_md_xr(real, num, den, NOP_MUL);
44705dfecf96Smrg}
44715dfecf96Smrg
44725dfecf96Smrgstatic INLINE void
44735dfecf96Smrgrdiv_bi_fr(n_real *real, long num, long den)
44745dfecf96Smrg{
44755dfecf96Smrg    rop_bi_fr_md_xr(real, num, den, NOP_DIV);
44765dfecf96Smrg}
44775dfecf96Smrg
44785dfecf96Smrgstatic int
44795dfecf96Smrgcmp_bi_fr(mpi *bignum, long num, long den)
44805dfecf96Smrg{
44815dfecf96Smrg    int cmp;
44825dfecf96Smrg    mpr cmp1, cmp2;
44835dfecf96Smrg
44845dfecf96Smrg    mpr_init(&cmp1);
44855dfecf96Smrg    mpi_set(mpr_num(&cmp1), bignum);
44865dfecf96Smrg    mpi_seti(mpr_den(&cmp1), 1);
44875dfecf96Smrg
44885dfecf96Smrg    mpr_init(&cmp2);
44895dfecf96Smrg    mpr_seti(&cmp2, num, den);
44905dfecf96Smrg
44915dfecf96Smrg    cmp = mpr_cmp(&cmp1, &cmp2);
44925dfecf96Smrg    mpr_clear(&cmp1);
44935dfecf96Smrg    mpr_clear(&cmp2);
44945dfecf96Smrg
44955dfecf96Smrg    return (cmp);
44965dfecf96Smrg}
44975dfecf96Smrg
44985dfecf96Smrg
44995dfecf96Smrg/************************************************************************
45005dfecf96Smrg * BIGNUM BIGRATIO
45015dfecf96Smrg ************************************************************************/
45025dfecf96Smrgstatic void
45035dfecf96Smrgrop_bi_br_as_xr(n_real *real, mpr *bigratio, int nop)
45045dfecf96Smrg{
45055dfecf96Smrg    mpi iop;
45065dfecf96Smrg    mpr *bigr = XALLOC(mpr);
45075dfecf96Smrg
45085dfecf96Smrg    mpi_init(&iop);
45095dfecf96Smrg    mpi_set(&iop, RBI(real));
45105dfecf96Smrg    mpr_init(bigr);
45115dfecf96Smrg    mpr_set(bigr, bigratio);
45125dfecf96Smrg
45135dfecf96Smrg    mpi_mul(&iop, &iop, mpr_den(bigratio));
45145dfecf96Smrg
45155dfecf96Smrg    if (nop == NOP_ADD)
45165dfecf96Smrg	mpi_add(mpr_num(bigr), &iop, mpr_num(bigr));
45175dfecf96Smrg    else
45185dfecf96Smrg	mpi_sub(mpr_num(bigr), &iop, mpr_num(bigr));
45195dfecf96Smrg    mpi_clear(&iop);
45205dfecf96Smrg
45215dfecf96Smrg    RCLEAR_BI(real);
45225dfecf96Smrg    RBR(real) = bigr;
45235dfecf96Smrg    RTYPE(real) = N_BIGRATIO;
45245dfecf96Smrg    rbr_canonicalize(real);
45255dfecf96Smrg}
45265dfecf96Smrg
45275dfecf96Smrgstatic void
45285dfecf96Smrgrop_bi_br_md_xr(n_real *real, mpr *bigratio, int nop)
45295dfecf96Smrg{
45305dfecf96Smrg    mpr *bigr = XALLOC(mpr);
45315dfecf96Smrg
45325dfecf96Smrg    mpr_init(bigr);
45335dfecf96Smrg    if (nop == NOP_MUL)
45345dfecf96Smrg	mpr_set(bigr, bigratio);
45355dfecf96Smrg    else
45365dfecf96Smrg	mpr_inv(bigr, bigratio);
45375dfecf96Smrg
45385dfecf96Smrg    mpi_mul(mpr_num(bigr), RBI(real), mpr_num(bigr));
45395dfecf96Smrg
45405dfecf96Smrg    RCLEAR_BI(real);
45415dfecf96Smrg    RBR(real) = bigr;
45425dfecf96Smrg    RTYPE(real) = N_BIGRATIO;
45435dfecf96Smrg    rbr_canonicalize(real);
45445dfecf96Smrg}
45455dfecf96Smrg
45465dfecf96Smrgstatic INLINE void
45475dfecf96Smrgradd_bi_br(n_real *real, mpr *bigratio)
45485dfecf96Smrg{
45495dfecf96Smrg    rop_bi_br_as_xr(real, bigratio, NOP_ADD);
45505dfecf96Smrg}
45515dfecf96Smrg
45525dfecf96Smrgstatic INLINE void
45535dfecf96Smrgrsub_bi_br(n_real *real, mpr *bigratio)
45545dfecf96Smrg{
45555dfecf96Smrg    rop_bi_br_as_xr(real, bigratio, NOP_SUB);
45565dfecf96Smrg}
45575dfecf96Smrg
45585dfecf96Smrgstatic INLINE void
45595dfecf96Smrgrmul_bi_br(n_real *real, mpr *bigratio)
45605dfecf96Smrg{
45615dfecf96Smrg    rop_bi_br_md_xr(real, bigratio, NOP_MUL);
45625dfecf96Smrg}
45635dfecf96Smrg
45645dfecf96Smrgstatic INLINE void
45655dfecf96Smrgrdiv_bi_br(n_real *real, mpr *bigratio)
45665dfecf96Smrg{
45675dfecf96Smrg    rop_bi_br_md_xr(real, bigratio, NOP_DIV);
45685dfecf96Smrg}
45695dfecf96Smrg
45705dfecf96Smrgstatic int
45715dfecf96Smrgcmp_bi_br(mpi *bignum, mpr *bigratio)
45725dfecf96Smrg{
45735dfecf96Smrg    int cmp;
45745dfecf96Smrg    mpr cmp1;
45755dfecf96Smrg
45765dfecf96Smrg    mpr_init(&cmp1);
45775dfecf96Smrg    mpi_set(mpr_num(&cmp1), bignum);
45785dfecf96Smrg    mpi_seti(mpr_den(&cmp1), 1);
45795dfecf96Smrg
45805dfecf96Smrg    cmp = mpr_cmp(&cmp1, bigratio);
45815dfecf96Smrg    mpr_clear(&cmp1);
45825dfecf96Smrg
45835dfecf96Smrg    return (cmp);
45845dfecf96Smrg}
45855dfecf96Smrg
45865dfecf96Smrg
45875dfecf96Smrg/************************************************************************
45885dfecf96Smrg * FIXRATIO FIXNUM
45895dfecf96Smrg ************************************************************************/
45905dfecf96Smrgstatic void
45915dfecf96Smrgrop_fr_fi_as_xr(n_real *real, long op, int nop)
45925dfecf96Smrg{
45935dfecf96Smrg    int fit;
45945dfecf96Smrg    long value = 0, num = RFRN(real), den = RFRD(real);
45955dfecf96Smrg
45965dfecf96Smrg    fit = !fi_fi_mul_overflow(op, den);
45975dfecf96Smrg
45985dfecf96Smrg    if (fit) {
45995dfecf96Smrg	value = op * den;
46005dfecf96Smrg	if (nop == NOP_ADD)
46015dfecf96Smrg	    fit = !fi_fi_add_overflow(value, num);
46025dfecf96Smrg	else
46035dfecf96Smrg	    fit = !fi_fi_sub_overflow(value, num);
46045dfecf96Smrg    }
46055dfecf96Smrg    if (fit) {
46065dfecf96Smrg	if (nop == NOP_ADD)
46075dfecf96Smrg	    RFRN(real) = num + value;
46085dfecf96Smrg	else
46095dfecf96Smrg	    RFRN(real) = num - value;
46105dfecf96Smrg	rfr_canonicalize(real);
46115dfecf96Smrg    }
46125dfecf96Smrg    else {
46135dfecf96Smrg	mpi iop;
46145dfecf96Smrg	mpr *bigr = XALLOC(mpr);
46155dfecf96Smrg
46165dfecf96Smrg	mpr_init(bigr);
46175dfecf96Smrg	mpr_seti(bigr, num, den);
46185dfecf96Smrg	mpi_init(&iop);
46195dfecf96Smrg	mpi_seti(&iop, op);
46205dfecf96Smrg	mpi_muli(&iop, &iop, den);
46215dfecf96Smrg	if (nop == NOP_ADD)
46225dfecf96Smrg	    mpi_add(mpr_num(bigr), mpr_num(bigr), &iop);
46235dfecf96Smrg	else
46245dfecf96Smrg	    mpi_sub(mpr_num(bigr), mpr_num(bigr), &iop);
46255dfecf96Smrg	mpi_clear(&iop);
46265dfecf96Smrg	RBR(real) = bigr;
46275dfecf96Smrg	RTYPE(real) = N_BIGRATIO;
46285dfecf96Smrg	rbr_canonicalize(real);
46295dfecf96Smrg    }
46305dfecf96Smrg}
46315dfecf96Smrg
46325dfecf96Smrgstatic void
46335dfecf96Smrgrop_fr_fi_md_xr(n_real *real, long op, int nop)
46345dfecf96Smrg{
46355dfecf96Smrg    long num = RFRN(real), den = RFRD(real);
46365dfecf96Smrg
46375dfecf96Smrg    if (nop == NOP_MUL) {
46385dfecf96Smrg	if (!fi_fi_mul_overflow(op, num)) {
46395dfecf96Smrg	    RFRN(real) = op * num;
46405dfecf96Smrg	    rfr_canonicalize(real);
46415dfecf96Smrg	    return;
46425dfecf96Smrg	}
46435dfecf96Smrg    }
46445dfecf96Smrg    else if (!fi_fi_mul_overflow(op, den)) {
46455dfecf96Smrg	RFRD(real) = op * den;
46465dfecf96Smrg	rfr_canonicalize(real);
46475dfecf96Smrg	return;
46485dfecf96Smrg    }
46495dfecf96Smrg
46505dfecf96Smrg    {
46515dfecf96Smrg	mpr *bigr = XALLOC(mpr);
46525dfecf96Smrg
46535dfecf96Smrg	mpr_init(bigr);
46545dfecf96Smrg	mpr_seti(bigr, num, den);
46555dfecf96Smrg	if (nop == NOP_MUL)
46565dfecf96Smrg	    mpr_muli(bigr, bigr, op);
46575dfecf96Smrg	else
46585dfecf96Smrg	    mpr_divi(bigr, bigr, op);
46595dfecf96Smrg	RBR(real) = bigr;
46605dfecf96Smrg	RTYPE(real) = N_BIGRATIO;
46615dfecf96Smrg	rbr_canonicalize(real);
46625dfecf96Smrg    }
46635dfecf96Smrg}
46645dfecf96Smrg
46655dfecf96Smrgstatic INLINE void
46665dfecf96Smrgradd_fr_fi(n_real *real, long op)
46675dfecf96Smrg{
46685dfecf96Smrg    rop_fr_fi_as_xr(real, op, NOP_ADD);
46695dfecf96Smrg}
46705dfecf96Smrg
46715dfecf96Smrgstatic INLINE void
46725dfecf96Smrgrsub_fr_fi(n_real *real, long op)
46735dfecf96Smrg{
46745dfecf96Smrg    rop_fr_fi_as_xr(real, op, NOP_SUB);
46755dfecf96Smrg}
46765dfecf96Smrg
46775dfecf96Smrgstatic INLINE void
46785dfecf96Smrgrmul_fr_fi(n_real *real, long op)
46795dfecf96Smrg{
46805dfecf96Smrg    rop_fr_fi_md_xr(real, op, NOP_MUL);
46815dfecf96Smrg}
46825dfecf96Smrg
46835dfecf96Smrgstatic INLINE void
46845dfecf96Smrgrdiv_fr_fi(n_real *real, long op)
46855dfecf96Smrg{
46865dfecf96Smrg    rop_fr_fi_md_xr(real, op, NOP_DIV);
46875dfecf96Smrg}
46885dfecf96Smrg
46895dfecf96Smrgstatic INLINE int
46905dfecf96Smrgcmp_fr_fi(long num, long den, long fixnum)
46915dfecf96Smrg{
46925dfecf96Smrg    return (cmp_flonum((double)num / (double)den, (double)fixnum));
46935dfecf96Smrg}
46945dfecf96Smrg
46955dfecf96Smrg
46965dfecf96Smrg/************************************************************************
46975dfecf96Smrg * FIXRATIO BIGNUM
46985dfecf96Smrg ************************************************************************/
46995dfecf96Smrgstatic void
47005dfecf96Smrgrop_fr_bi_as_xr(n_real *real, mpi *bignum, int nop)
47015dfecf96Smrg{
47025dfecf96Smrg    mpi iop;
47035dfecf96Smrg    mpr *bigr = XALLOC(mpr);
47045dfecf96Smrg
47055dfecf96Smrg    mpr_init(bigr);
47065dfecf96Smrg    mpr_seti(bigr, RFRN(real), RFRD(real));
47075dfecf96Smrg
47085dfecf96Smrg    mpi_init(&iop);
47095dfecf96Smrg    mpi_set(&iop, bignum);
47105dfecf96Smrg    mpi_muli(&iop, &iop, RFRD(real));
47115dfecf96Smrg
47125dfecf96Smrg    if (nop == NOP_ADD)
47135dfecf96Smrg	mpi_add(mpr_num(bigr), mpr_num(bigr), &iop);
47145dfecf96Smrg    else
47155dfecf96Smrg	mpi_sub(mpr_num(bigr), mpr_num(bigr), &iop);
47165dfecf96Smrg    mpi_clear(&iop);
47175dfecf96Smrg
47185dfecf96Smrg    RBR(real) = bigr;
47195dfecf96Smrg    RTYPE(real) = N_BIGRATIO;
47205dfecf96Smrg    rbr_canonicalize(real);
47215dfecf96Smrg}
47225dfecf96Smrg
47235dfecf96Smrgstatic void
47245dfecf96Smrgrop_fr_bi_md_xr(n_real *real, mpi *bignum, int nop)
47255dfecf96Smrg{
47265dfecf96Smrg    mpr *bigr = XALLOC(mpr);
47275dfecf96Smrg
47285dfecf96Smrg    mpr_init(bigr);
47295dfecf96Smrg    mpr_seti(bigr, RFRN(real), RFRD(real));
47305dfecf96Smrg
47315dfecf96Smrg    if (nop == NOP_MUL)
47325dfecf96Smrg	mpi_mul(mpr_num(bigr), mpr_num(bigr), bignum);
47335dfecf96Smrg    else
47345dfecf96Smrg	mpi_mul(mpr_den(bigr), mpr_den(bigr), bignum);
47355dfecf96Smrg
47365dfecf96Smrg    RBR(real) = bigr;
47375dfecf96Smrg    RTYPE(real) = N_BIGRATIO;
47385dfecf96Smrg    rbr_canonicalize(real);
47395dfecf96Smrg}
47405dfecf96Smrg
47415dfecf96Smrgstatic INLINE void
47425dfecf96Smrgradd_fr_bi(n_real *real, mpi *bignum)
47435dfecf96Smrg{
47445dfecf96Smrg    rop_fr_bi_as_xr(real, bignum, NOP_ADD);
47455dfecf96Smrg}
47465dfecf96Smrg
47475dfecf96Smrgstatic INLINE void
47485dfecf96Smrgrsub_fr_bi(n_real *real, mpi *bignum)
47495dfecf96Smrg{
47505dfecf96Smrg    rop_fr_bi_as_xr(real, bignum, NOP_SUB);
47515dfecf96Smrg}
47525dfecf96Smrg
47535dfecf96Smrgstatic INLINE void
47545dfecf96Smrgrmul_fr_bi(n_real *real, mpi *bignum)
47555dfecf96Smrg{
47565dfecf96Smrg    rop_fr_bi_md_xr(real, bignum, NOP_MUL);
47575dfecf96Smrg}
47585dfecf96Smrg
47595dfecf96Smrgstatic INLINE void
47605dfecf96Smrgrdiv_fr_bi(n_real *real, mpi *bignum)
47615dfecf96Smrg{
47625dfecf96Smrg    rop_fr_bi_md_xr(real, bignum, NOP_DIV);
47635dfecf96Smrg}
47645dfecf96Smrg
47655dfecf96Smrgstatic int
47665dfecf96Smrgcmp_fr_bi(long num, long den, mpi *bignum)
47675dfecf96Smrg{
47685dfecf96Smrg    int cmp;
47695dfecf96Smrg    mpr cmp1, cmp2;
47705dfecf96Smrg
47715dfecf96Smrg    mpr_init(&cmp1);
47725dfecf96Smrg    mpr_seti(&cmp1, num, den);
47735dfecf96Smrg
47745dfecf96Smrg    mpr_init(&cmp2);
47755dfecf96Smrg    mpi_set(mpr_num(&cmp2), bignum);
47765dfecf96Smrg    mpi_seti(mpr_den(&cmp2), 1);
47775dfecf96Smrg
47785dfecf96Smrg    cmp = mpr_cmp(&cmp1, &cmp2);
47795dfecf96Smrg    mpr_clear(&cmp1);
47805dfecf96Smrg    mpr_clear(&cmp2);
47815dfecf96Smrg
47825dfecf96Smrg    return (cmp);
47835dfecf96Smrg}
47845dfecf96Smrg
47855dfecf96Smrg
47865dfecf96Smrg/************************************************************************
47875dfecf96Smrg * FIXRATIO FIXRATIO
47885dfecf96Smrg ************************************************************************/
47895dfecf96Smrgstatic void
47905dfecf96Smrgrop_fr_fr_as_xr(n_real *real, long num2, long den2, int nop)
47915dfecf96Smrg{
47925dfecf96Smrg    int fit;
47935dfecf96Smrg    long num1 = RFRN(real), den1 = RFRD(real), num = 0, den = 0;
47945dfecf96Smrg
47955dfecf96Smrg    fit = !fi_fi_mul_overflow(num1, den2);
47965dfecf96Smrg    if (fit) {
47975dfecf96Smrg	num = num1 * den2;
47985dfecf96Smrg	fit = !fi_fi_mul_overflow(num2, den1);
47995dfecf96Smrg	if (fit) {
48005dfecf96Smrg	    den = num2 * den1;
48015dfecf96Smrg	    if (nop == NOP_ADD) {
48025dfecf96Smrg		if ((fit = !fi_fi_add_overflow(num, den)) != 0)
48035dfecf96Smrg		    num += den;
48045dfecf96Smrg	    }
48055dfecf96Smrg	    else if ((fit = !fi_fi_sub_overflow(num, den)) != 0)
48065dfecf96Smrg		num -= den;
48075dfecf96Smrg	    if (fit) {
48085dfecf96Smrg		fit = !fi_fi_mul_overflow(den1, den2);
48095dfecf96Smrg		if (fit)
48105dfecf96Smrg		    den = den1 * den2;
48115dfecf96Smrg	    }
48125dfecf96Smrg	}
48135dfecf96Smrg    }
48145dfecf96Smrg    if (fit) {
48155dfecf96Smrg	RFRN(real) = num;
48165dfecf96Smrg	RFRD(real) = den;
48175dfecf96Smrg	rfr_canonicalize(real);
48185dfecf96Smrg    }
48195dfecf96Smrg    else {
48205dfecf96Smrg	mpi iop;
48215dfecf96Smrg	mpr *bigr = XALLOC(mpr);
48225dfecf96Smrg
48235dfecf96Smrg	mpr_init(bigr);
48245dfecf96Smrg	mpr_seti(bigr, num1, den1);
48255dfecf96Smrg	mpi_muli(mpr_den(bigr), mpr_den(bigr), den2);
48265dfecf96Smrg	mpi_init(&iop);
48275dfecf96Smrg	mpi_seti(&iop, num2);
48285dfecf96Smrg	mpi_muli(&iop, &iop, den1);
48295dfecf96Smrg	mpi_muli(mpr_num(bigr), mpr_num(bigr), den2);
48305dfecf96Smrg	if (nop == NOP_ADD)
48315dfecf96Smrg	    mpi_add(mpr_num(bigr), mpr_num(bigr), &iop);
48325dfecf96Smrg	else
48335dfecf96Smrg	    mpi_sub(mpr_num(bigr), mpr_num(bigr), &iop);
48345dfecf96Smrg	mpi_clear(&iop);
48355dfecf96Smrg	RBR(real) = bigr;
48365dfecf96Smrg	RTYPE(real) = N_BIGRATIO;
48375dfecf96Smrg	rbr_canonicalize(real);
48385dfecf96Smrg    }
48395dfecf96Smrg}
48405dfecf96Smrg
48415dfecf96Smrgstatic void
48425dfecf96Smrgrop_fr_fr_md_xr(n_real *real, long num2, long den2, int nop)
48435dfecf96Smrg{
48445dfecf96Smrg    int fit;
48455dfecf96Smrg    long num1 = RFRN(real), den1 = RFRD(real), num = 0, den = 0;
48465dfecf96Smrg
48475dfecf96Smrg    if (nop == NOP_MUL) {
48485dfecf96Smrg	fit = !fi_fi_mul_overflow(num1, num2) && !fi_fi_mul_overflow(den1, den2);
48495dfecf96Smrg	if (fit) {
48505dfecf96Smrg	    num = num1 * num2;
48515dfecf96Smrg	    den = den1 * den2;
48525dfecf96Smrg	}
48535dfecf96Smrg    }
48545dfecf96Smrg    else {
48555dfecf96Smrg	fit = !fi_fi_mul_overflow(num1, den2) && !fi_fi_mul_overflow(den1, num2);
48565dfecf96Smrg	if (fit) {
48575dfecf96Smrg	    num = num1 * den2;
48585dfecf96Smrg	    den = den1 * num2;
48595dfecf96Smrg	}
48605dfecf96Smrg    }
48615dfecf96Smrg
48625dfecf96Smrg    if (fit) {
48635dfecf96Smrg	RFRN(real) = num;
48645dfecf96Smrg	RFRD(real) = den;
48655dfecf96Smrg	rfr_canonicalize(real);
48665dfecf96Smrg    }
48675dfecf96Smrg    else {
48685dfecf96Smrg	mpr *bigr = XALLOC(mpr);
48695dfecf96Smrg
48705dfecf96Smrg	mpr_init(bigr);
48715dfecf96Smrg
48725dfecf96Smrg	if (nop == NOP_MUL) {
48735dfecf96Smrg	    mpr_seti(bigr, num1, den1);
48745dfecf96Smrg	    mpi_muli(mpr_num(bigr), mpr_num(bigr), num2);
48755dfecf96Smrg	    mpi_muli(mpr_den(bigr), mpr_den(bigr), den2);
48765dfecf96Smrg	}
48775dfecf96Smrg	else {
48785dfecf96Smrg	    mpr_seti(bigr, num1, num2);
48795dfecf96Smrg	    mpi_muli(mpr_num(bigr), mpr_num(bigr), den2);
48805dfecf96Smrg	    mpi_muli(mpr_den(bigr), mpr_den(bigr), den1);
48815dfecf96Smrg	}
48825dfecf96Smrg
48835dfecf96Smrg	RBR(real) = bigr;
48845dfecf96Smrg	RTYPE(real) = N_BIGRATIO;
48855dfecf96Smrg	rbr_canonicalize(real);
48865dfecf96Smrg    }
48875dfecf96Smrg}
48885dfecf96Smrg
48895dfecf96Smrgstatic INLINE void
48905dfecf96Smrgradd_fr_fr(n_real *real, long num, long den)
48915dfecf96Smrg{
48925dfecf96Smrg    rop_fr_fr_as_xr(real, num, den, NOP_ADD);
48935dfecf96Smrg}
48945dfecf96Smrg
48955dfecf96Smrgstatic INLINE void
48965dfecf96Smrgrsub_fr_fr(n_real *real, long num, long den)
48975dfecf96Smrg{
48985dfecf96Smrg    rop_fr_fr_as_xr(real, num, den, NOP_SUB);
48995dfecf96Smrg}
49005dfecf96Smrg
49015dfecf96Smrgstatic INLINE void
49025dfecf96Smrgrmul_fr_fr(n_real *real, long num, long den)
49035dfecf96Smrg{
49045dfecf96Smrg    rop_fr_fr_md_xr(real, num, den, NOP_MUL);
49055dfecf96Smrg}
49065dfecf96Smrg
49075dfecf96Smrgstatic INLINE void
49085dfecf96Smrgrdiv_fr_fr(n_real *real, long num, long den)
49095dfecf96Smrg{
49105dfecf96Smrg    rop_fr_fr_md_xr(real, num, den, NOP_DIV);
49115dfecf96Smrg}
49125dfecf96Smrg
49135dfecf96Smrgstatic INLINE int
49145dfecf96Smrgcmp_fr_fr(long num1, long den1, long num2, long den2)
49155dfecf96Smrg{
49165dfecf96Smrg    return (cmp_flonum((double)num1 / (double)den1,
49175dfecf96Smrg		       (double)num2 / (double)den2));
49185dfecf96Smrg}
49195dfecf96Smrg
49205dfecf96Smrg
49215dfecf96Smrg/************************************************************************
49225dfecf96Smrg * FIXRATIO BIGRATIO
49235dfecf96Smrg ************************************************************************/
49245dfecf96Smrgstatic void
49255dfecf96Smrgrop_fr_br_asmd_xr(n_real *real, mpr *bigratio, int nop)
49265dfecf96Smrg{
49275dfecf96Smrg    mpr *bigr = XALLOC(mpr);
49285dfecf96Smrg
49295dfecf96Smrg    mpr_init(bigr);
49305dfecf96Smrg    mpr_seti(bigr, RFRN(real), RFRD(real));
49315dfecf96Smrg
49325dfecf96Smrg    switch (nop) {
49335dfecf96Smrg	case NOP_ADD:
49345dfecf96Smrg	    mpr_add(bigr, bigr, bigratio);
49355dfecf96Smrg	    break;
49365dfecf96Smrg	case NOP_SUB:
49375dfecf96Smrg	    mpr_sub(bigr, bigr, bigratio);
49385dfecf96Smrg	    break;
49395dfecf96Smrg	case NOP_MUL:
49405dfecf96Smrg	    mpr_mul(bigr, bigr, bigratio);
49415dfecf96Smrg	    break;
49425dfecf96Smrg	default:
49435dfecf96Smrg	    mpr_div(bigr, bigr, bigratio);
49445dfecf96Smrg	    break;
49455dfecf96Smrg    }
49465dfecf96Smrg
49475dfecf96Smrg    RBR(real) = bigr;
49485dfecf96Smrg    RTYPE(real) = N_BIGRATIO;
49495dfecf96Smrg    rbr_canonicalize(real);
49505dfecf96Smrg}
49515dfecf96Smrg
49525dfecf96Smrgstatic INLINE void
49535dfecf96Smrgradd_fr_br(n_real *real, mpr *bigratio)
49545dfecf96Smrg{
49555dfecf96Smrg    rop_fr_br_asmd_xr(real, bigratio, NOP_ADD);
49565dfecf96Smrg}
49575dfecf96Smrg
49585dfecf96Smrgstatic INLINE void
49595dfecf96Smrgrsub_fr_br(n_real *real, mpr *bigratio)
49605dfecf96Smrg{
49615dfecf96Smrg    rop_fr_br_asmd_xr(real, bigratio, NOP_SUB);
49625dfecf96Smrg}
49635dfecf96Smrg
49645dfecf96Smrgstatic INLINE void
49655dfecf96Smrgrmul_fr_br(n_real *real, mpr *bigratio)
49665dfecf96Smrg{
49675dfecf96Smrg    rop_fr_br_asmd_xr(real, bigratio, NOP_MUL);
49685dfecf96Smrg}
49695dfecf96Smrg
49705dfecf96Smrgstatic INLINE void
49715dfecf96Smrgrdiv_fr_br(n_real *real, mpr *bigratio)
49725dfecf96Smrg{
49735dfecf96Smrg    rop_fr_br_asmd_xr(real, bigratio, NOP_DIV);
49745dfecf96Smrg}
49755dfecf96Smrg
49765dfecf96Smrgstatic int
49775dfecf96Smrgcmp_fr_br(long num, long den, mpr *bigratio)
49785dfecf96Smrg{
49795dfecf96Smrg    int cmp;
49805dfecf96Smrg    mpr cmp1;
49815dfecf96Smrg
49825dfecf96Smrg    mpr_init(&cmp1);
49835dfecf96Smrg    mpr_seti(&cmp1, num, den);
49845dfecf96Smrg
49855dfecf96Smrg    cmp = mpr_cmp(&cmp1, bigratio);
49865dfecf96Smrg    mpr_clear(&cmp1);
49875dfecf96Smrg
49885dfecf96Smrg    return (cmp);
49895dfecf96Smrg}
49905dfecf96Smrg
49915dfecf96Smrg
49925dfecf96Smrg/************************************************************************
49935dfecf96Smrg * BIGRATIO FIXNUM
49945dfecf96Smrg ************************************************************************/
49955dfecf96Smrgstatic void
49965dfecf96Smrgrop_br_fi_asmd_xr(n_real *real, long fixnum, int nop)
49975dfecf96Smrg{
49985dfecf96Smrg    mpr *bigratio = RBR(real);
49995dfecf96Smrg
50005dfecf96Smrg    switch (nop) {
50015dfecf96Smrg	case NOP_ADD:
50025dfecf96Smrg	    mpr_addi(bigratio, bigratio, fixnum);
50035dfecf96Smrg	    break;
50045dfecf96Smrg	case NOP_SUB:
50055dfecf96Smrg	    mpr_subi(bigratio, bigratio, fixnum);
50065dfecf96Smrg	    break;
50075dfecf96Smrg	case NOP_MUL:
50085dfecf96Smrg	    mpr_muli(bigratio, bigratio, fixnum);
50095dfecf96Smrg	    break;
50105dfecf96Smrg	default:
50115dfecf96Smrg	    if (fixnum == 0)
50125dfecf96Smrg		fatal_error(DIVIDE_BY_ZERO);
50135dfecf96Smrg	    mpr_divi(bigratio, bigratio, fixnum);
50145dfecf96Smrg	    break;
50155dfecf96Smrg    }
50165dfecf96Smrg    rbr_canonicalize(real);
50175dfecf96Smrg}
50185dfecf96Smrg
50195dfecf96Smrgstatic INLINE void
50205dfecf96Smrgradd_br_fi(n_real *real, long fixnum)
50215dfecf96Smrg{
50225dfecf96Smrg    rop_br_fi_asmd_xr(real, fixnum, NOP_ADD);
50235dfecf96Smrg}
50245dfecf96Smrg
50255dfecf96Smrgstatic INLINE void
50265dfecf96Smrgrsub_br_fi(n_real *real, long fixnum)
50275dfecf96Smrg{
50285dfecf96Smrg    rop_br_fi_asmd_xr(real, fixnum, NOP_SUB);
50295dfecf96Smrg}
50305dfecf96Smrg
50315dfecf96Smrgstatic INLINE void
50325dfecf96Smrgrmul_br_fi(n_real *real, long fixnum)
50335dfecf96Smrg{
50345dfecf96Smrg    rop_br_fi_asmd_xr(real, fixnum, NOP_MUL);
50355dfecf96Smrg}
50365dfecf96Smrg
50375dfecf96Smrgstatic INLINE void
50385dfecf96Smrgrdiv_br_fi(n_real *real, long fixnum)
50395dfecf96Smrg{
50405dfecf96Smrg    rop_br_fi_asmd_xr(real, fixnum, NOP_DIV);
50415dfecf96Smrg}
50425dfecf96Smrg
50435dfecf96Smrgstatic int
50445dfecf96Smrgcmp_br_fi(mpr *bigratio, long fixnum)
50455dfecf96Smrg{
50465dfecf96Smrg    int cmp;
50475dfecf96Smrg    mpr cmp2;
50485dfecf96Smrg
50495dfecf96Smrg    mpr_init(&cmp2);
50505dfecf96Smrg    mpr_seti(&cmp2, fixnum, 1);
50515dfecf96Smrg    cmp = mpr_cmp(bigratio, &cmp2);
50525dfecf96Smrg    mpr_clear(&cmp2);
50535dfecf96Smrg
50545dfecf96Smrg    return (cmp);
50555dfecf96Smrg}
50565dfecf96Smrg
50575dfecf96Smrg
50585dfecf96Smrg/************************************************************************
50595dfecf96Smrg * BIGRATIO BIGNUM
50605dfecf96Smrg ************************************************************************/
50615dfecf96Smrgstatic void
50625dfecf96Smrgrop_br_bi_as_xr(n_real *real, mpi *bignum, int nop)
50635dfecf96Smrg{
50645dfecf96Smrg    mpi iop;
50655dfecf96Smrg
50665dfecf96Smrg    mpi_init(&iop);
50675dfecf96Smrg    mpi_set(&iop, bignum);
50685dfecf96Smrg
50695dfecf96Smrg    mpi_mul(&iop, &iop, RBRD(real));
50705dfecf96Smrg    if (nop == NOP_ADD)
50715dfecf96Smrg	mpi_add(RBRN(real), RBRN(real), &iop);
50725dfecf96Smrg    else
50735dfecf96Smrg	mpi_sub(RBRN(real), RBRN(real), &iop);
50745dfecf96Smrg    mpi_clear(&iop);
50755dfecf96Smrg    rbr_canonicalize(real);
50765dfecf96Smrg}
50775dfecf96Smrg
50785dfecf96Smrgstatic INLINE void
50795dfecf96Smrgradd_br_bi(n_real *real, mpi *bignum)
50805dfecf96Smrg{
50815dfecf96Smrg    rop_br_bi_as_xr(real, bignum, NOP_ADD);
50825dfecf96Smrg}
50835dfecf96Smrg
50845dfecf96Smrgstatic INLINE void
50855dfecf96Smrgrsub_br_bi(n_real *real, mpi *bignum)
50865dfecf96Smrg{
50875dfecf96Smrg    rop_br_bi_as_xr(real, bignum, NOP_SUB);
50885dfecf96Smrg}
50895dfecf96Smrg
50905dfecf96Smrgstatic INLINE void
50915dfecf96Smrgrmul_br_bi(n_real *real, mpi *bignum)
50925dfecf96Smrg{
50935dfecf96Smrg    mpi_mul(RBRN(real), RBRN(real), bignum);
50945dfecf96Smrg    rbr_canonicalize(real);
50955dfecf96Smrg}
50965dfecf96Smrg
50975dfecf96Smrgstatic INLINE void
50985dfecf96Smrgrdiv_br_bi(n_real *real, mpi *bignum)
50995dfecf96Smrg{
51005dfecf96Smrg    mpi_mul(RBRD(real), RBRD(real), bignum);
51015dfecf96Smrg    rbr_canonicalize(real);
51025dfecf96Smrg}
51035dfecf96Smrg
51045dfecf96Smrgstatic int
51055dfecf96Smrgcmp_br_bi(mpr *bigratio, mpi *bignum)
51065dfecf96Smrg{
51075dfecf96Smrg    int cmp;
51085dfecf96Smrg    mpr cmp1;
51095dfecf96Smrg
51105dfecf96Smrg    mpr_init(&cmp1);
51115dfecf96Smrg    mpi_set(mpr_num(&cmp1), bignum);
51125dfecf96Smrg    mpi_seti(mpr_den(&cmp1), 1);
51135dfecf96Smrg
51145dfecf96Smrg    cmp = mpr_cmp(bigratio, &cmp1);
51155dfecf96Smrg    mpr_clear(&cmp1);
51165dfecf96Smrg
51175dfecf96Smrg    return (cmp);
51185dfecf96Smrg}
51195dfecf96Smrg
51205dfecf96Smrg
51215dfecf96Smrg/************************************************************************
51225dfecf96Smrg * BIGRATIO FIXRATIO
51235dfecf96Smrg ************************************************************************/
51245dfecf96Smrgstatic void
51255dfecf96Smrgrop_br_fr_asmd_xr(n_real *real, long num, long den, int nop)
51265dfecf96Smrg{
51275dfecf96Smrg    mpr *bigratio = RBR(real), rop;
51285dfecf96Smrg
51295dfecf96Smrg    mpr_init(&rop);
51305dfecf96Smrg    mpr_seti(&rop, num, den);
51315dfecf96Smrg    switch (nop) {
51325dfecf96Smrg	case NOP_ADD:
51335dfecf96Smrg	    mpr_add(bigratio, bigratio, &rop);
51345dfecf96Smrg	    break;
51355dfecf96Smrg	case NOP_SUB:
51365dfecf96Smrg	    mpr_sub(bigratio, bigratio, &rop);
51375dfecf96Smrg	    break;
51385dfecf96Smrg	case NOP_MUL:
51395dfecf96Smrg	    mpr_mul(bigratio, bigratio, &rop);
51405dfecf96Smrg	    break;
51415dfecf96Smrg	default:
51425dfecf96Smrg	    mpr_div(bigratio, bigratio, &rop);
51435dfecf96Smrg	    break;
51445dfecf96Smrg    }
51455dfecf96Smrg    mpr_clear(&rop);
51465dfecf96Smrg    rbr_canonicalize(real);
51475dfecf96Smrg}
51485dfecf96Smrg
51495dfecf96Smrgstatic INLINE void
51505dfecf96Smrgradd_br_fr(n_real *real, long num, long den)
51515dfecf96Smrg{
51525dfecf96Smrg    rop_br_fr_asmd_xr(real, num, den, NOP_ADD);
51535dfecf96Smrg}
51545dfecf96Smrg
51555dfecf96Smrgstatic INLINE void
51565dfecf96Smrgrsub_br_fr(n_real *real, long num, long den)
51575dfecf96Smrg{
51585dfecf96Smrg    rop_br_fr_asmd_xr(real, num, den, NOP_SUB);
51595dfecf96Smrg}
51605dfecf96Smrg
51615dfecf96Smrgstatic INLINE void
51625dfecf96Smrgrmul_br_fr(n_real *real, long num, long den)
51635dfecf96Smrg{
51645dfecf96Smrg    rop_br_fr_asmd_xr(real, num, den, NOP_MUL);
51655dfecf96Smrg}
51665dfecf96Smrg
51675dfecf96Smrgstatic INLINE void
51685dfecf96Smrgrdiv_br_fr(n_real *real, long num, long den)
51695dfecf96Smrg{
51705dfecf96Smrg    rop_br_fr_asmd_xr(real, num, den, NOP_DIV);
51715dfecf96Smrg}
51725dfecf96Smrg
51735dfecf96Smrgstatic int
51745dfecf96Smrgcmp_br_fr(mpr *bigratio, long num, long den)
51755dfecf96Smrg{
51765dfecf96Smrg    int cmp;
51775dfecf96Smrg    mpr cmp2;
51785dfecf96Smrg
51795dfecf96Smrg    mpr_init(&cmp2);
51805dfecf96Smrg    mpr_seti(&cmp2, num, den);
51815dfecf96Smrg    cmp = mpr_cmp(bigratio, &cmp2);
51825dfecf96Smrg    mpr_clear(&cmp2);
51835dfecf96Smrg
51845dfecf96Smrg    return (cmp);
51855dfecf96Smrg}
51865dfecf96Smrg
51875dfecf96Smrg
51885dfecf96Smrg/************************************************************************
51895dfecf96Smrg * BIGRATIO BIGRATIO
51905dfecf96Smrg ************************************************************************/
51915dfecf96Smrgstatic INLINE void
51925dfecf96Smrgradd_br_br(n_real *real, mpr *bigratio)
51935dfecf96Smrg{
51945dfecf96Smrg    mpr_add(RBR(real), RBR(real), bigratio);
51955dfecf96Smrg    rbr_canonicalize(real);
51965dfecf96Smrg}
51975dfecf96Smrg
51985dfecf96Smrgstatic INLINE void
51995dfecf96Smrgrsub_br_br(n_real *real, mpr *bigratio)
52005dfecf96Smrg{
52015dfecf96Smrg    mpr_sub(RBR(real), RBR(real), bigratio);
52025dfecf96Smrg    rbr_canonicalize(real);
52035dfecf96Smrg}
52045dfecf96Smrg
52055dfecf96Smrgstatic INLINE void
52065dfecf96Smrgrmul_br_br(n_real *real, mpr *bigratio)
52075dfecf96Smrg{
52085dfecf96Smrg    mpr_mul(RBR(real), RBR(real), bigratio);
52095dfecf96Smrg    rbr_canonicalize(real);
52105dfecf96Smrg}
52115dfecf96Smrg
52125dfecf96Smrgstatic INLINE void
52135dfecf96Smrgrdiv_br_br(n_real *real, mpr *bigratio)
52145dfecf96Smrg{
52155dfecf96Smrg    mpr_div(RBR(real), RBR(real), bigratio);
52165dfecf96Smrg    rbr_canonicalize(real);
52175dfecf96Smrg}
52185dfecf96Smrg
52195dfecf96Smrgstatic INLINE int
52205dfecf96Smrgcmp_br_br(mpr *op1, mpr *op2)
52215dfecf96Smrg{
52225dfecf96Smrg    return (mpr_cmp(op1, op2));
52235dfecf96Smrg}
5224