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