1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393 |
- /* arith08.c Copyright (C) 1990-2002 Codemist Ltd */
- /*
- * Arithmetic functions.
- */
- /*
- * This code may be used and modified, and redistributed in binary
- * or source form, subject to the "CCL Public License", which should
- * accompany it. This license is a variant on the BSD license, and thus
- * permits use of code derived from this in either open and commercial
- * projects: but it does require that updates to this code be made
- * available back to the originators of the package.
- * Before merging other code in with this or linking this code
- * with other packages or libraries please check that the license terms
- * of the other material are compatible with those of this.
- */
- /* Signature: 2f37a658 08-Apr-2002 */
- #include <stdarg.h>
- #include <string.h>
- #include <ctype.h>
- #include <math.h>
- #include <float.h>
- #include "machine.h"
- #include "tags.h"
- #include "cslerror.h"
- #include "externs.h"
- #include "arith.h"
- #include "entries.h"
- #ifdef TIMEOUT
- #include "timeout.h"
- #endif
- #ifdef COMMON
- static Lisp_Object MS_CDECL Lboole(Lisp_Object nil, int nargs, ...)
- {
- Lisp_Object r, op, a, b;
- va_list aa;
- argcheck(nargs, 3, "boole");
- va_start(aa, nargs);
- op = va_arg(aa, Lisp_Object);
- a = va_arg(aa, Lisp_Object);
- b = va_arg(aa, Lisp_Object);
- va_end(aa);
- switch (op)
- {
- case fixnum_of_int(boole_clr):
- return onevalue(fixnum_of_int(0));
- case fixnum_of_int(boole_and):
- r = logand2(a, b);
- break;
- case fixnum_of_int(boole_andc2):
- push(a);
- b = lognot(b);
- pop(a);
- errexit();
- r = logand2(a, b);
- break;
- case fixnum_of_int(boole_1):
- return onevalue(a);
- case fixnum_of_int(boole_andc1):
- push(b);
- a = lognot(a);
- pop(b);
- errexit();
- r = logand2(a, b);
- break;
- case fixnum_of_int(boole_2):
- return onevalue(b);
- case fixnum_of_int(boole_xor):
- r = logxor2(a, b);
- break;
- case fixnum_of_int(boole_ior):
- r = logior2(a, b);
- break;
- case fixnum_of_int(boole_nor):
- a = logior2(a, b);
- errexit();
- r = lognot(a);
- break;
- case fixnum_of_int(boole_eqv):
- r = logeqv2(a, b);
- break;
- case fixnum_of_int(boole_c2):
- r = lognot(b);
- break;
- case fixnum_of_int(boole_orc2):
- b = lognot(b);
- errexit();
- r = logior2(a, b);
- break;
- case fixnum_of_int(boole_c1):
- r = lognot(a);
- break;
- case fixnum_of_int(boole_orc1):
- push(b);
- a = lognot(a);
- pop(b);
- errexit();
- r = logior2(a, b);
- break;
- case fixnum_of_int(boole_nand):
- a = logand2(a, b);
- errexit();
- r = lognot(a);
- break;
- case fixnum_of_int(boole_set):
- return onevalue(fixnum_of_int(-1));
- default:
- return aerror1("bad arg for boole", op);
- }
- errexit();
- return onevalue(r);
- }
- static Lisp_Object Lbyte(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- a = cons(a, b);
- errexit();
- return onevalue(a);
- }
- static Lisp_Object Lbyte_position(Lisp_Object nil, Lisp_Object a)
- {
- if (!consp(a)) return aerror1("byte-position", a);
- else return onevalue(qcdr(a));
- }
- static Lisp_Object Lbyte_size(Lisp_Object nil, Lisp_Object a)
- {
- if (!consp(a)) return aerror1("byte-size", a);
- else return onevalue(qcar(a));
- }
- static Lisp_Object Lcomplex_2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- /* /* Need to coerce a and b to the same type here... */
- a = make_complex(a, b);
- errexit();
- return onevalue(a);
- }
- static Lisp_Object Lcomplex_1(Lisp_Object nil, Lisp_Object a)
- {
- /* /* Need to make zero of same type as a */
- a = make_complex(a, fixnum_of_int(0));
- errexit();
- return onevalue(a);
- }
- static Lisp_Object Lconjugate(Lisp_Object nil, Lisp_Object a)
- {
- if (!is_number(a)) return aerror1("conjugate", a);
- if (is_numbers(a) && is_complex(a))
- { Lisp_Object r = real_part(a),
- i = imag_part(a);
- push(r);
- i = negate(i);
- pop(r);
- errexit();
- a = make_complex(r, i);
- errexit();
- return onevalue(a);
- }
- else return onevalue(a);
- }
- static Lisp_Object Ldecode_float(Lisp_Object nil, Lisp_Object a)
- {
- double d = float_of_number(a), neg = 1.0;
- int x;
- Lisp_Object sign;
- if (!is_float(a)) return aerror("decode-float");
- if (d < 0.0) d = -d, neg = -1.0;
- if (d == 0.0) x = 0;
- else
- { d = frexp(d, &x);
- if (d == 1.0) d = 0.5, x++;
- }
- if (is_sfloat(a)) sign = make_sfloat(neg);
- else sign = make_boxfloat(neg, type_of_header(flthdr(a)));
- errexit();
- push(sign);
- if (is_sfloat(a)) a = make_sfloat(d);
- else a = make_boxfloat(d, type_of_header(flthdr(a)));
- pop(sign);
- errexit();
- mv_2 = fixnum_of_int(x);
- mv_3 = sign;
- return nvalues(a, 3);
- }
- /*
- * The next two functions depend on IEEE-format floating point numbers.
- * They are (thus?) potentially a portability trap, but may suffice for
- * MOST systems. I need to test the handling of double precision values
- * on computers that store the two words of a double in each of the
- * possible orders. If the exponent field in floats was not stored in the
- * position that would be 0x7f800000 in an integer my treatment of short
- * floats would fail, so I have already assumed that that is so. I think.
- */
- static Lisp_Object Lfloat_denormalized_p(Lisp_Object nil, Lisp_Object a)
- {
- int x = 0;
- switch ((int)a & TAG_BITS)
- {
- #ifdef COMMON
- case TAG_SFLOAT:
- if ((a & 0x7fffffff) == TAG_SFLOAT) return onevalue(nil); /* 0.0 */
- x = (int32)a & 0x7f800000;
- return onevalue(x == 0 ? lisp_true : nil);
- #endif
- case TAG_BOXFLOAT:
- switch (type_of_header(flthdr(a)))
- {
- #ifdef COMMON
- case TYPE_SINGLE_FLOAT:
- if (single_float_val(a) == 0.0) return onevalue(nil);
- x = ((Single_Float *)((char *)a-TAG_BOXFLOAT))->f.i & 0x7f800000;
- return onevalue(x == 0 ? lisp_true : nil);
- case TYPE_LONG_FLOAT:
- if (long_float_val(a) == 0.0) return onevalue(nil);
- x = ((Long_Float *)((char *)a-TAG_BOXFLOAT)
- )->f.i[current_fp_rep&FP_WORD_ORDER ? 0 : 1] & 0x7ff00000;
- return onevalue(x == 0 ? lisp_true : nil);
- #endif
- case TYPE_DOUBLE_FLOAT:
- if (double_float_val(a) == 0.0) return onevalue(nil);
- x = ((Double_Float *)((char *)a-TAG_BOXFLOAT)
- )->f.i[current_fp_rep&FP_WORD_ORDER ? 0 : 1] & 0x7ff00000;
- return onevalue(x == 0 ? lisp_true : nil);
- }
- default:
- break;
- }
- return onevalue(nil);
- }
- static Lisp_Object Lfloat_infinity_p(Lisp_Object nil, Lisp_Object a)
- {
- /*
- * The issue of NaN values is one I do not want to worry about at present.
- * I deem anything with the largest possibl exponent value to be infinite.
- */
- int x = 0;
- switch ((int)a & TAG_BITS)
- {
- #ifdef COMMON
- case TAG_SFLOAT:
- x = (int32)a & 0x7f800000;
- return onevalue(x == 0x7f800000 ? lisp_true : nil);
- #endif
- case TAG_BOXFLOAT:
- switch (type_of_header(flthdr(a)))
- {
- #ifdef COMMON
- case TYPE_SINGLE_FLOAT:
- if (single_float_val(a) == 0.0) return onevalue(nil);
- x = ((Single_Float *)((char *)a-TAG_BOXFLOAT))->f.i & 0x7f800000;
- return onevalue(x == 0x7f800000 ? lisp_true : nil);
- case TYPE_LONG_FLOAT:
- if (long_float_val(a) == 0.0) return onevalue(nil);
- x = ((Long_Float *)((char *)a-TAG_BOXFLOAT)
- )->f.i[current_fp_rep&FP_WORD_ORDER ? 0 : 1] & 0x7ff00000;
- return onevalue(x == 0x7ff00000 ? lisp_true : nil);
- #endif
- case TYPE_DOUBLE_FLOAT:
- if (double_float_val(a) == 0.0) return onevalue(nil);
- x = ((Double_Float *)((char *)a-TAG_BOXFLOAT)
- )->f.i[current_fp_rep&FP_WORD_ORDER ? 0 : 1] & 0x7ff00000;
- return onevalue(x == 0x7ff00000 ? lisp_true : nil);
- }
- default:
- break;
- }
- return onevalue(nil);
- }
- static Lisp_Object Ldenominator(Lisp_Object nil, Lisp_Object a)
- {
- CSL_IGNORE(nil);
- if (!is_number(a)) return aerror1("denominator", a);
- if (is_numbers(a) && is_ratio(a))
- return onevalue(denominator(a));
- else return onevalue(fixnum_of_int(1));
- }
- static Lisp_Object MS_CDECL Ldeposit_field(Lisp_Object nil, int nargs, ...)
- {
- va_list aa;
- Lisp_Object a, b, c;
- CSL_IGNORE(nil);
- CSL_IGNORE(nargs);
- va_start(aa, nargs);
- a = va_arg(aa, Lisp_Object);
- b = va_arg(aa, Lisp_Object);
- c = va_arg(aa, Lisp_Object);
- va_end(aa);
- return aerror("deposit-field");
- }
- static Lisp_Object MS_CDECL Ldpb(Lisp_Object nil, int nargs, ...)
- {
- va_list aa;
- Lisp_Object a, b, c;
- CSL_IGNORE(nil);
- CSL_IGNORE(nargs);
- va_start(aa, nargs);
- a = va_arg(aa, Lisp_Object);
- b = va_arg(aa, Lisp_Object);
- c = va_arg(aa, Lisp_Object);
- va_end(aa);
- return aerror("dpb");
- }
- static Lisp_Object Lffloor(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- CSL_IGNORE(nil);
- CSL_IGNORE(a);
- CSL_IGNORE(b);
- return aerror("ffloor");
- }
- /*
- * The functions such as float-digits, float-precision, float-radix are
- * coded here assuming that IEEE-style arithmetic is being used. If this is
- * not so then all the code in this file needs review. Furthermore I will
- * be lazy about NaNs and denormalised numbers for now and come back to
- * worry about them later on if I am really forced to.
- */
- static Lisp_Object Lfloat_digits(Lisp_Object nil, Lisp_Object a)
- {
- int tag = (int)a & TAG_BITS;
- CSL_IGNORE(nil);
- switch (tag)
- {
- #ifdef COMMON
- case TAG_SFLOAT:
- return onevalue(fixnum_of_int(20));
- #endif
- case TAG_BOXFLOAT:
- switch (type_of_header(flthdr(a)))
- {
- #ifdef COMMON
- case TYPE_SINGLE_FLOAT:
- return onevalue(fixnum_of_int(24));
- #endif
- default:
- return onevalue(fixnum_of_int(53));
- }
- default:
- return aerror("float-digits");
- }
- }
- static Lisp_Object Lfloat_precision(Lisp_Object nil, Lisp_Object a)
- {
- int tag = (int)a & TAG_BITS;
- double d = float_of_number(a);
- CSL_IGNORE(nil);
- if (d == 0.0) return onevalue(fixnum_of_int(0));
- /* /* I do not cope with de-normalised numbers here */
- switch (tag)
- {
- #ifdef COMMON
- case TAG_SFLOAT:
- return onevalue(fixnum_of_int(20));
- #endif
- case TAG_BOXFLOAT:
- switch (type_of_header(flthdr(a)))
- {
- #ifdef COMMON
- case TYPE_SINGLE_FLOAT:
- return onevalue(fixnum_of_int(24));
- #endif
- default:
- return onevalue(fixnum_of_int(53));
- }
- default:
- return aerror("float-precision");
- }
- }
- static Lisp_Object Lfloat_radix(Lisp_Object nil, Lisp_Object a)
- {
- CSL_IGNORE(nil);
- CSL_IGNORE(a);
- return onevalue(fixnum_of_int(FLT_RADIX));
- }
- static Lisp_Object Lfloat_sign2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- double d = float_of_number(b);
- CSL_IGNORE(nil);
- if (float_of_number(a) < 0.0) d = -d;
- if (is_sfloat(b)) return onevalue(make_sfloat(d));
- else if (!is_bfloat(b)) return aerror1("bad arg for float-sign", b);
- else return onevalue(make_boxfloat(d, type_of_header(flthdr(b))));
- }
- static Lisp_Object Lfloat_sign1(Lisp_Object nil, Lisp_Object a)
- {
- double d = float_of_number(a);
- CSL_IGNORE(nil);
- if (d < 0.0) d = -1.0; else d = 1.0;
- if (is_sfloat(a)) return onevalue(make_sfloat(d));
- else if (!is_bfloat(a)) return aerror1("bad arg for float-sign", a);
- else return onevalue(make_boxfloat(d, type_of_header(flthdr(a))));
- }
- static Lisp_Object Lfround(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- CSL_IGNORE(nil);
- CSL_IGNORE(a);
- CSL_IGNORE(b);
- return aerror("fround");
- }
- static Lisp_Object Lftruncate(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- CSL_IGNORE(nil);
- CSL_IGNORE(a);
- CSL_IGNORE(b);
- return aerror("ftruncate");
- }
- Lisp_Object MS_CDECL Lgcd_n(Lisp_Object nil, int nargs, ...)
- {
- va_list a;
- int i;
- Lisp_Object r;
- if (nargs == 0) return fixnum_of_int(0);
- va_start(a, nargs);
- push_args(a, nargs);
- /*
- * The actual args have been passed a C args - I can not afford to
- * risk garbage collection until they have all been moved somewhere safe,
- * and here that safe place is the Lisp stack. I have to delay checking for
- * overflow on same until all args have been pushed.
- */
- stackcheck0(nargs);
- pop(r);
- for (i = 1; i<nargs; i++)
- { Lisp_Object w;
- if (r == fixnum_of_int(1))
- { popv(nargs-i);
- break;
- }
- pop(w);
- r = gcd(r, w);
- errexitn(nargs-i-1);
- }
- return onevalue(r);
- }
- Lisp_Object Lgcd(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- a = gcd(a, b);
- errexit();
- return onevalue(a);
- }
- Lisp_Object Lgcd_1(Lisp_Object nil, Lisp_Object a)
- {
- CSL_IGNORE(nil);
- return onevalue(a);
- }
- static Lisp_Object Limagpart(Lisp_Object nil, Lisp_Object a)
- {
- CSL_IGNORE(nil);
- if (!is_number(a)) return aerror1("imagpart", a);
- if (is_numbers(a) && is_complex(a))
- return onevalue(imag_part(a));
- /* /* the 0.0 returned here ought to be the same type as a has */
- else return onevalue(fixnum_of_int(0));
- }
- static Lisp_Object Linteger_decode_float(Lisp_Object nil, Lisp_Object a)
- {
- double d = float_of_number(a);
- int tag = (int)a & TAG_BITS, x, neg = 0;
- int32 a1, a2;
- CSL_IGNORE(nil);
- if (!is_float(a)) return aerror("integer-decode-float");
- if (d == 0.0)
- #ifdef COMMON
- { mv_2 = fixnum_of_int(0);
- mv_3 = fixnum_of_int(1);
- nvalues(a, 3);
- }
- #else
- return list3(a, fixnum_of_int(0), fixnum_of_int(1));
- #endif
- if (d < 0.0) d = -d, neg = 1;
- d = frexp(d, &x);
- if (d == 1.0) d = 0.5, x++;
- #ifdef COMMON
- if (tag == TAG_SFLOAT)
- { d *= TWO_20;
- x -= 20;
- a1 = (int32)d;
- a = fixnum_of_int(a1);
- }
- else if (tag == TAG_BOXFLOAT &&
- type_of_header(flthdr(a)) == TYPE_SINGLE_FLOAT)
- { d *= TWO_24;
- x -= 24;
- a1 = (int32)d;
- a = fixnum_of_int(a1);
- }
- else
- #endif
- { d *= TWO_22;
- a1 = (int32)d;
- d -= (double)a1;
- a2 = (int32)(d*TWO_31); /* This conversion should be exact */
- x -= 53;
- a = make_two_word_bignum(a1, a2);
- errexit();
- }
- #ifdef COMMON
- { mv_2 = fixnum_of_int(x);
- mv_3 = neg ? fixnum_of_int(-1) : fixnum_of_int(1);
- return nvalues(a, 3);
- }
- #else
- return list3(a, fixnum_of_int(x),
- neg ? fixnum_of_int(-1) : fixnum_of_int(1));
- #endif
- }
- static Lisp_Object Linteger_length(Lisp_Object nil, Lisp_Object a)
- {
- a = Labsval(nil, a);
- errexit();
- return Lmsd(nil, a);
- }
- static Lisp_Object Lldb(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- CSL_IGNORE(nil);
- CSL_IGNORE(a);
- CSL_IGNORE(b);
- return aerror("ldb");
- }
- Lisp_Object MS_CDECL Llcm_n(Lisp_Object nil, int nargs, ...)
- {
- va_list a;
- int i;
- Lisp_Object r;
- if (nargs == 0) return onevalue(fixnum_of_int(1));
- va_start(a, nargs);
- push_args(a, nargs);
- stackcheck0(nargs);
- pop(r);
- for (i = 1; i<nargs; i++)
- { Lisp_Object w;
- pop(w);
- r = lcm(r, w);
- errexitn(nargs-i-1);
- }
- return onevalue(r);
- }
- Lisp_Object Llcm(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- a = lcm(a, b);
- errexit();
- return onevalue(a);
- }
- Lisp_Object Llcm_1(Lisp_Object nil, Lisp_Object a)
- {
- CSL_IGNORE(nil);
- return onevalue(a);
- }
- static Lisp_Object Lldb_test(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- CSL_IGNORE(nil);
- CSL_IGNORE(a);
- CSL_IGNORE(b);
- return aerror("ldb-test");
- }
- static Lisp_Object Llogbitp(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- CSL_IGNORE(nil);
- CSL_IGNORE(a);
- CSL_IGNORE(b);
- return aerror("logbitp");
- }
- static Lisp_Object Llogcount(Lisp_Object nil, Lisp_Object a)
- {
- CSL_IGNORE(nil);
- CSL_IGNORE(a);
- return aerror("logcount");
- }
- static Lisp_Object Llogtest(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- CSL_IGNORE(nil);
- CSL_IGNORE(a);
- CSL_IGNORE(b);
- return aerror("logtest");
- }
- static Lisp_Object Lmask_field(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- CSL_IGNORE(nil);
- CSL_IGNORE(a);
- CSL_IGNORE(b);
- return aerror("mask-field");
- }
- static Lisp_Object Lnumerator(Lisp_Object nil, Lisp_Object a)
- {
- CSL_IGNORE(nil);
- if (!is_number(a)) return aerror1("numerator", a);
- if (is_numbers(a) && is_ratio(a))
- return onevalue(numerator(a));
- else return onevalue(a);
- }
- static Lisp_Object Lrealpart(Lisp_Object nil, Lisp_Object a)
- {
- CSL_IGNORE(nil);
- if (!is_number(a)) return aerror1("realpart", a);
- if (is_numbers(a) && is_complex(a))
- return onevalue(real_part(a));
- else return onevalue(a);
- }
- static Lisp_Object Lscale_float(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- double d = float_of_number(a);
- CSL_IGNORE(nil);
- if (!is_fixnum(b)) return aerror("scale-float");
- d = ldexp(d, int_of_fixnum(b));
- if (is_sfloat(a)) return onevalue(make_sfloat(d));
- else if (!is_bfloat(a)) return aerror1("bad arg for scale-float", a);
- else return onevalue(make_boxfloat(d, type_of_header(flthdr(a))));
- }
- #else /* COMMON */
- Lisp_Object Lgcd(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- a = gcd(a, b);
- errexit();
- return onevalue(a);
- }
- Lisp_Object Llcm(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- Lisp_Object g;
- push2(b, a);
- g = gcd(a, b);
- errexitn(2);
- pop(a);
- a = quot2(a, g);
- pop(b);
- errexit();
- a = times2(a, b);
- errexit();
- return onevalue(a);
- }
- #endif /* COMMON */
- #define FIX_TRUNCATE 0
- #define FIX_ROUND 1
- #define FIX_FLOOR 2
- #define FIX_CEILING 3
- static Lisp_Object lisp_fix_sub(Lisp_Object a, int roundmode)
- /*
- * This converts from a double to a Lisp integer, which will
- * quite often have to be a bignum. No overflow is permitted - the
- * result can always be accurate.
- */
- {
- int32 a0, a1, a2, a3;
- int x, x1;
- CSLbool negative;
- double d = float_of_number(a);
- if (M2_31_1 < d && d < TWO_31)
- { int32 a = (int32)d;
- /*
- * If my floating point value is in the range -(2^31+1) to +2^31 (exclusive)
- * then when C truncates it I will get an integer in the inclusive range
- * from -2^31 to 2^31-1, i.e. the whole range of C 32-bit integers.
- * If I then apply a rounding mode other than truncation I may just have
- * overflow, which I have to detect specially.
- */
- int32 w;
- double f;
- switch (roundmode)
- {
- case FIX_TRUNCATE:
- break; /* C casts truncate, so this is OK */
- case FIX_ROUND:
- f = d - (double)a;
- if (f > 0.5)
- { if (a == 0x7fffffff) return make_two_word_bignum(1, 0);
- else a++;
- }
- else if (f < -0.5)
- { if (a == ~0x7fffffff)
- return make_two_word_bignum(-2, 0x7fffffff);
- else a--;
- }
- /* The rounding rule on the next lines show what I do in 1/2ulp cases */
- else if (f == 0.5) a = (a+1) & ~1;
- else if (f == -0.5)
- { if (a == ~0x7fffffff)
- return make_two_word_bignum(-2, 0x7fffffff);
- else a = a & ~1;
- }
- break;
- case FIX_FLOOR:
- f = d - (double)a;
- if (f < 0.0)
- { if (a == ~0x7fffffff)
- return make_two_word_bignum(-2, 0x7fffffff);
- else a--;
- }
- break;
- case FIX_CEILING:
- f = d - (double)a;
- if (f > 0.0)
- { if (a == 0x7fffffff) return make_two_word_bignum(1, 0);
- else a++;
- }
- break;
- }
- w = a & fix_mask;
- if (w == 0 || w == fix_mask) return fixnum_of_int(a);
- else if (!signed_overflow(a)) return make_one_word_bignum(a);
- else if (a > 0) return make_two_word_bignum(0, a);
- else return make_two_word_bignum(-1, clear_top_bit(a));
- }
- if (d < 0.0) d = -d, negative = YES;
- else negative = NO;
- d = frexp(d, &x); /* 0.5 <= abs(d) < 1.0, x = the (binary) exponent */
- if (d == 1.0) d = 0.5, x++;
- d *= TWO_31;
- a1 = (int32)d; /* 2^31 > d >= 2^30 */
- d -= (double)a1;
- a2 = (unsigned32)(d*TWO_31); /* This conversion should be exact */
- if (negative)
- { if (a2 == 0) a1 = -a1;
- else a2 = clear_top_bit(-a2), a1 = ~a1;
- }
- x -= 62;
- if (x < 0) /* Need to shift right x places */
- { x = -x; /* The shift amount here can be 31 at most... */
- a3 = a2 << (32 - x);
- a2 = clear_top_bit((a2 >> x) | (a1 << (31 - x)));
- #ifdef SIGNED_SHIFTS_ARE_LOGICAL
- if (a1 < 0) a1 = (a1 >> x) | (((int32)-1) << (31 - x));
- else a1 = a1 >> x;
- #else
- a1 = a1 >> x;
- #endif
- switch (roundmode)
- {
- case FIX_TRUNCATE:
- if (a1 < 0 && a3 != 0) /* proper rounding on -ve values */
- { a2++;
- if (a2 < 0) /* carry */
- { a2 = 0;
- a1++;
- }
- }
- break;
- case FIX_ROUND:
- if ((a3 & 0x80000000U) != 0 &&
- (a3 != ~0x7fffffff || (a2 & 1) != 0))
- { a2++;
- if (a2 < 0) /* carry */
- { a2 = 0;
- a1++;
- }
- }
- break;
- case FIX_FLOOR: /* Comes out in wash of 2's complement */
- break;
- case FIX_CEILING:
- if (a3 != 0)
- { a2++;
- if (a2 < 0) /* carry */
- { a2 = 0;
- a1++;
- }
- }
- break;
- }
- return make_two_word_bignum(a1, a2);
- }
- /* Now the double-length value (a1,a2) is correct and exact, and it
- * needs shifting left by x bits. This will give a 3 or more word bignum.
- * Note that no rounding etc is needed at all here since there are no
- * fractional bits in the representation.
- */
- if (a1 < 0)
- { a0 = -1;
- a1 = clear_top_bit(a1);
- }
- else a0 = 0;
- x1 = x / 31;
- x = x % 31;
- a0 = (a0 << x) | (a1 >> (31-x));
- a1 = clear_top_bit(a1 << x) | (a2 >> (31-x));
- a2 = clear_top_bit(a2 << x);
- return make_n_word_bignum(a0, a1, a2, x1);
- }
- #ifdef COMMON
- static Lisp_Object lisp_fix_ratio(Lisp_Object a, int roundmode)
- /*
- * This converts from a ratio to a Lisp integer. It has to apply
- * the specified rounding regime.
- */
- {
- Lisp_Object p, q, r, nil = C_nil;;
- p = numerator(a);
- q = denominator(a);
- push2(q, p);
- r = quot2(p, q);
- errexitn(2);
- p = stack[0];
- stack[0] = r;
- p = Cremainder(p, stack[-1]);
- pop2(r, q);
- errexit();
- switch (roundmode)
- {
- case FIX_TRUNCATE:
- break;
- case FIX_ROUND:
- /* /* This case unfinished at present */
- break;
- case FIX_FLOOR:
- if (minusp(p))
- { push(r);
- p = plus2(p, q);
- pop(r);
- errexit();
- r = sub1(r);
- errexit();
- }
- break;
- case FIX_CEILING:
- if (plusp(p))
- { push(r);
- p = difference2(p, q);
- pop(r);
- errexit();
- r = add1(r);
- errexit();
- }
- break;
- }
- mv_2 = p;
- return nvalues(r, 2);
- }
- #endif
- static Lisp_Object lisp_fix(Lisp_Object a, int roundmode)
- {
- Lisp_Object r, nil;
- push(a);
- r = lisp_fix_sub(a, roundmode);
- errexitn(1);
- a = stack[0];
- stack[0] = r;
- a = difference2(a, r);
- pop(r);
- errexit();
- mv_2 = a;
- return nvalues(r, 2);
- }
- static Lisp_Object lisp_ifix(Lisp_Object a, Lisp_Object b, int roundmode)
- {
- Lisp_Object q, r, nil;
- if (is_float(a) || is_float(b))
- { double p = float_of_number(a), q = float_of_number(b), d = p/q;
- a = make_boxfloat(d, TYPE_DOUBLE_FLOAT);
- errexit();
- r = lisp_fix(a, roundmode);
- errexit();
- push(r);
- a = make_boxfloat(float_of_number(mv_2)*q, TYPE_DOUBLE_FLOAT);
- pop(r);
- errexit();
- mv_2 = a;
- return nvalues(r, 2);
- }
- push2(a, b);
- q = quot2(a, b);
- errexitn(2);
- a = stack[-1];
- b = stack[0];
- push(q);
- r = Cremainder(a, b);
- errexitn(3);
- switch (roundmode)
- {
- case FIX_TRUNCATE:
- break;
- case FIX_ROUND:
- popv(3); return aerror("two-arg ROUND");
- case FIX_FLOOR:
- if (!minusp(r)) break;
- r = plus2(r, stack[-1]);
- errexitn(3);
- q = stack[0];
- push(r);
- q = sub1(q);
- pop(r);
- errexitn(3);
- stack[0] = q;
- break;
- case FIX_CEILING:
- if (!plusp(r)) break;
- r = difference2(r, stack[-1]);
- errexitn(3);
- q = stack[0];
- push(r);
- q = add1(q);
- pop(r);
- errexitn(3);
- stack[0] = q;
- break;
- }
- pop3(q, b, a);
- mv_2 = r;
- return nvalues(q, 2);
- }
- /*
- * So far I have not implemented support for rational numbers in the 2-arg
- * versions of these functions. /*
- */
- static Lisp_Object Lceiling_2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- CSL_IGNORE(nil);
- if (!is_number(a) || !is_number(b)) return aerror1("ceiling", a);
- return lisp_ifix(a, b, FIX_CEILING);
- }
- static Lisp_Object Lfloor_2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- CSL_IGNORE(nil);
- if (!is_number(a) || !is_number(b)) return aerror1("floor", a);
- return lisp_ifix(a, b, FIX_FLOOR);
- }
- static Lisp_Object Lround_2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- CSL_IGNORE(nil);
- if (!is_number(a) || !is_number(b)) return aerror1("round", a);
- return lisp_ifix(a, b, FIX_ROUND);
- }
- Lisp_Object Ltruncate_2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- CSL_IGNORE(nil);
- if (!is_number(a) || !is_number(b)) return aerror1("truncate", a);
- return lisp_ifix(a, b, FIX_TRUNCATE);
- }
- static Lisp_Object Lceiling(Lisp_Object nil, Lisp_Object a)
- {
- CSL_IGNORE(nil);
- if (!is_number(a)) return aerror1("ceiling", a);
- #ifdef COMMON
- if (is_numbers(a) && is_ratio(a)) return lisp_fix_ratio(a, FIX_CEILING);
- #endif
- if (!is_float(a)) { mv_2 = fixnum_of_int(0); return nvalues(a, 2); }
- return lisp_fix(a, FIX_CEILING);
- }
- static Lisp_Object Lfloor(Lisp_Object nil, Lisp_Object a)
- {
- CSL_IGNORE(nil);
- if (!is_number(a)) return aerror1("floor", a);
- #ifdef COMMON
- if (is_numbers(a) && is_ratio(a)) return lisp_fix_ratio(a, FIX_FLOOR);
- #endif
- if (!is_float(a)) { mv_2 = fixnum_of_int(0); return nvalues(a, 2); }
- return lisp_fix(a, FIX_FLOOR);
- }
- static Lisp_Object Lround(Lisp_Object nil, Lisp_Object a)
- {
- CSL_IGNORE(nil);
- if (!is_number(a)) return aerror1("round", a);
- #ifdef COMMON
- if (is_numbers(a) && is_ratio(a)) return lisp_fix_ratio(a, FIX_ROUND);
- #endif
- if (!is_float(a)) { mv_2 = fixnum_of_int(0); return nvalues(a, 2); }
- return lisp_fix(a, FIX_ROUND);
- }
- Lisp_Object Ltruncate(Lisp_Object nil, Lisp_Object a)
- {
- CSL_IGNORE(nil);
- if (!is_number(a)) return aerror1("fix", a);
- #ifdef COMMON
- if (is_numbers(a) && is_ratio(a)) return lisp_fix_ratio(a, FIX_TRUNCATE);
- #endif
- if (!is_float(a)) { mv_2 = fixnum_of_int(0); return nvalues(a, 2); }
- return lisp_fix(a, FIX_TRUNCATE);
- }
- /*
- * The following macro is expected to select out the 32-bit word within a
- * floating point number that has the exponent field packed within it.
- * On IEEE-format machines I expect to find the exponent in the
- * 0x7ff00000 bits within this word.
- */
- #define top_half(d) ((int32 *)&(d))[(~current_fp_rep) & FP_WORD_ORDER]
- /*
- * symbolic procedure safe!-fp!-plus(x,y);
- * if zerop x then y else if zerop y then x else
- * begin scalar u;
- * if x>0.0 and y>0.0 then
- * if x<!!plumax and y<!!plumax then go to ret else return nil;
- * if x<0.0 and y<0.0 then
- * if -x<!!plumax and -y<!!plumax then go to ret else return nil;
- * if abs x<!!plumin and abs y<!!plumin then return nil;
- * ret: return
- * if (u := plus2(x,y))=0.0
- * or x>0.0 and y>0.0 or x<0.0 and y<0.0 then u
- * else if abs u<(abs x)*!!fleps1 then 0.0 else u end;
- */
- static Lisp_Object Lsafe_fp_plus(Lisp_Object env, Lisp_Object a, Lisp_Object b)
- /*
- * safe!-fp!-plus must always be given floating point arguments. In
- * most reasonable cases it just returns the floating point sum. If
- * there was some chance that the sum might either overflow or underflow
- * then the value NIL is returned instead. The exact place where this
- * function starts to report overflow is not precisely defined - all that
- * is guaranteed is that if a result is returned then it will be of full
- * precision.
- */
- {
- Lisp_Object nil = C_nil;
- double aa, bb, cc;
- int32 ah, bh;
- if (!is_float(a) || !is_float(b)) return aerror2("safe-fp-plus", a, b);
- /*
- * I accept here that adding 0.0 to anything is always possible without
- * problem.
- */
- if ((aa = double_float_val(a)) == 0.0) return onevalue(b);
- if ((bb = double_float_val(b)) == 0.0) return onevalue(a);
- if (current_fp_rep & (FP_VAXREP|FP_IBMREP))
- return aerror("VAX or 370 FP rep");
- ah = top_half(aa);
- bh = top_half(bb);
- /*
- * Here I am going to assume IEEE-format numbers. I hope that I have
- * picked out the word containing the exponent and that it is positioned in
- * the word where I expect.
- */
- /*
- * I deem overflow POSSIBLE if both numbers have the same sign and if at
- * least one of them has an exponent 0x7fe (i.e. the highest exponent that
- * a non-infinite number can have).
- */
- if (ah >= 0)
- { if (bh >= 0)
- { if (ah >= 0x7fe00000 || bh >= 0x7fe00000) return onevalue(nil);
- cc = aa + bb;
- }
- else
- /*
- * I deem underflow POSSIBLE if the numbers have opposite signs and BOTH
- * of them have exponents less than 0x035 (which is 53 in decimal, and
- * IEEE-format numbers have 53-bit mantissas. The critical case would
- * be the subtraction
- * (53) 1 00000000000000000000 00000000000000000000000000000001
- * - (53) 1 00000000000000000000 00000000000000000000000000000000
- * where you see the LSB (which is all that is left after the subtraction)
- * has to be shifted left 52 bits to get to the position of the implied
- * leading 1 bit in the mantissa. As that happens 52 gets subtracted
- * from the exponent, leaving it as 1, the smallest exponent for a normalised
- * non-zero value.
- */
- { double eps, ra;
- bh &= 0x7fffffff;
- if (ah < 0x03500000 && bh < 0x03500000) return onevalue(nil);
- /*
- * The next few lines check to see if addition has led to cancellation of
- * leading digits to an extent greater than !!fleps1. The environent cell
- * of safe!-fp!-plus must be set to !!fleps, and then the value cell of
- * this symbol is accessed to obtain the limit.
- */
- eps = 0.0;
- if (is_symbol(env))
- { Lisp_Object ve = qvalue(env);
- if (is_float(ve)) eps = double_float_val(ve);
- }
- cc = aa + bb;
- ra = cc/aa;
- if (ra < 0.0) ra = -ra;
- if (ra < eps) cc = 0.0; /* Force to zero if too small */
- }
- }
- else
- { if (bh >= 0)
- { double eps, ra;
- ah &= 0x7fffffff;
- if (ah < 0x03500000 && bh < 0x03500000) return onevalue(nil);
- eps = 0.0;
- if (is_symbol(env))
- { Lisp_Object ve = qvalue(env);
- if (is_float(ve)) eps = double_float_val(ve);
- }
- cc = aa + bb;
- ra = cc/aa;
- if (ra < 0.0) ra = -ra;
- if (ra < eps) cc = 0.0;
- }
- else
- { ah &= 0x7fffffff;
- bh &= 0x7fffffff;
- if (ah >= 0x7fe00000 || bh >= 0x7fe00000) return onevalue(nil);
- cc = aa + bb;
- }
- }
- a = make_boxfloat(cc, TYPE_DOUBLE_FLOAT);
- errexit();
- return onevalue(a);
- }
- /*
- * symbolic procedure safe!-fp!-times(x,y);
- * if zerop x or zerop y then 0.0
- * else if x=1.0 then y else if y=1.0 then x else
- * begin scalar u,v; u := abs x; v := abs y;
- * if u>=1.0 and u<=!!timmax then
- * if v<=!!timmax then go to ret else return nil;
- * if u>!!timmax then if v<=1.0 then go to ret else return nil;
- * if u<1.0 and u>=!!timmin then
- * if v>=!!timmin then go to ret else return nil;
- * if u<!!timmin and v<1.0 then return nil;
- * ret: return times2(x,y) end;
- */
- static Lisp_Object Lsafe_fp_times(Lisp_Object nil,
- Lisp_Object a, Lisp_Object b)
- /*
- * safe!-fp!-times must always be given floating point arguments. In
- * most reasonable cases it just returns the floating point product. If
- * there was some chance that the product might either overflow or underflow
- * then the value NIL is returned instead. REDUCE requires that if this
- * function returns a non-overflow result than two such returned values
- * can be added witjout fear of overflow, as in a*b+c*d. Hence I ought to
- * report trouble slightly earlier than I might otherwise. - but REDUCE is
- * being changed to remove this oddity, and it seems it could only cause
- * trouble in (1.0,max)*(max, 1.0) complex multiplication, so I am not
- * going to worry...
- */
- {
- double aa, bb, cc;
- int32 ah, bh;
- if (!is_float(a) || !is_float(b)) return aerror2("safe-fp-times", a, b);
- /*
- * Multiplication by zero is handled as a special case here - doing so
- * means that I do not have to worry about the special case of zero
- * exponents later on, and it also avoids allocating fresh space to hold
- * a new floating point zero value.
- */
- if ((aa = double_float_val(a)) == 0.0) return onevalue(a);
- if ((bb = double_float_val(b)) == 0.0) return onevalue(b);
- if (current_fp_rep & (FP_VAXREP|FP_IBMREP))
- return aerror("VAX or 370 FP rep");
- ah = top_half(aa);
- bh = top_half(bb);
- /*
- * Here I am going to assume IEEE-format numbers. I hope that I have
- * picked out the word containing the exponent and that it is positioned in
- * the word where I expect.
- */
- ah = (ah >> 20) & 0x7ff;
- bh = (bh >> 20) & 0x7ff;
- ah = ah + bh;
- /*
- * I can estimate the value of the product by adding the exponents of the
- * two operands.
- */
- if (ah < 0x400 || ah >= 0xbfd) return onevalue(nil);
- cc = aa * bb;
- a = make_boxfloat(cc, TYPE_DOUBLE_FLOAT);
- errexit();
- return onevalue(a);
- }
- /*
- * symbolic procedure safe!-fp!-quot(x,y);
- * if zerop y then rdqoterr()
- * else if zerop x then 0.0 else if y=1.0 then x else
- * begin scalar u,v; u := abs x; v := abs y;
- * if u>=1.0 and u<=!!timmax then
- * if v>=!!timmin then go to ret else return nil;
- * if u>!!timmax then if v>=1.0 then go to ret else return nil;
- * if u<1.0 and u>=!!timmin then
- * if v<=!!timmax then go to ret else return nil;
- * if u<!!timmin and v>1.0 then return nil;
- * ret: return quotient(x,y) end;
- */
- static Lisp_Object Lsafe_fp_quot(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- double aa, bb, cc;
- int32 ah, bh;
- if (!is_float(a) || !is_float(b)) return aerror2("safe-fp-quot", a, b);
- if ((aa = double_float_val(a)) == 0.0) return onevalue(a);
- /*
- * I pass division by zero back to the general case here.
- */
- if ((bb = double_float_val(b)) == 0.0) return onevalue(nil);
- if (current_fp_rep & (FP_VAXREP|FP_IBMREP))
- return aerror("VAX or 370 FP rep");
- ah = top_half(aa);
- bh = top_half(bb);
- ah = (ah >> 20) & 0x7ff;
- bh = (bh >> 20) & 0x7ff;
- ah = ah - bh;
- if (ah <= -0x3fe || ah >= 0x3fe) return onevalue(nil);
- cc = aa / bb;
- a = make_boxfloat(cc, TYPE_DOUBLE_FLOAT);
- errexit();
- return onevalue(a);
- }
- /*
- * symbolic procedure safe!-fp!-pl(x,y);
- * % floating plus protect from under- and over-flows but no zero
- * % result check.
- * if zerop x then y else if zerop y then x
- * else if x>0 and y>0 then
- * if x<!!plumax and y<!!plumax then plus2(x,y) else nil
- * else if x<0 and y<0 then
- * if (-x<!!plumax and -y<!!plumax) then plus2(x,y) else nil
- * else if abs x<!!plumin or abs y<!!plumin then nil else plus2(x,y);
- */
- static Lisp_Object Lsafe_fp_pl(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- double aa, bb, cc;
- int32 ah, bh;
- if (!is_float(a) || !is_float(b)) return aerror2("safe-fp-pl", a, b);
- if ((aa = double_float_val(a)) == 0.0) return onevalue(b);
- if ((bb = double_float_val(b)) == 0.0) return onevalue(a);
- if (current_fp_rep & (FP_VAXREP|FP_IBMREP))
- return aerror("VAX or 370 FP rep");
- ah = top_half(aa);
- bh = top_half(bb);
- if (ah >= 0)
- { if (bh >= 0)
- { if (ah >= 0x7fe00000 || bh >= 0x7fe00000) return onevalue(nil);
- }
- else
- { bh &= 0x7fffffff;
- if (ah < 0x03500000 && bh < 0x03500000) return onevalue(nil);
- }
- }
- else
- { if (bh >= 0)
- { ah &= 0x7fffffff;
- if (ah < 0x03500000 && bh < 0x03500000) return onevalue(nil);
- }
- else
- { ah &= 0x7fffffff;
- bh &= 0x7fffffff;
- if (ah >= 0x7fe00000 || bh >= 0x7fe00000) return onevalue(nil);
- }
- }
- cc = aa + bb;
- a = make_boxfloat(cc, TYPE_DOUBLE_FLOAT);
- errexit();
- return onevalue(a);
- }
- /*
- * symbolic procedure safe!-fp!-pl0(x,y);
- * % protects floating plus against under-flow only.
- * if zerop x then y else if zerop y then x
- * else if abs x<!!plumin and abs y<!!plumin then nil else plus2(x,y);
- *
- * implement as safe!-fp!-pl without MUCH loss of speed.
- */
- static Lisp_Object Llose_precision(Lisp_Object nil,
- Lisp_Object a, Lisp_Object n)
- {
- double aa;
- char buffer[64];
- int32 nn;
- if (!is_float(a) || !is_fixnum(n)) return aerror2("lose_precision", a, n);
- nn = int_of_fixnum(n);
- if (nn <= 0 || nn >= 20) return onevalue(a);
- sprintf(buffer, "%.*g", (int)nn, double_float_val(a));
- if (sscanf(buffer, "%lg", &aa) != 1) return aerror("lose-precision");
- a = make_boxfloat(aa, TYPE_DOUBLE_FLOAT);
- errexit();
- return onevalue(a);
- }
- setup_type const arith08_setup[] =
- {
- /*
- * The next few are JUST for REDUCE, but they are expected to speed up
- * rounded-mode arithmetic rather a lot.
- */
- {"lose-precision", too_few_2, Llose_precision, wrong_no_2},
- {"safe-fp-plus", too_few_2, Lsafe_fp_plus, wrong_no_2},
- {"safe-fp-times", too_few_2, Lsafe_fp_times, wrong_no_2},
- {"safe-fp-quot", too_few_2, Lsafe_fp_quot, wrong_no_2},
- {"safe-fp-pl", too_few_2, Lsafe_fp_pl, wrong_no_2},
- {"safe-fp-pl0", too_few_2, Lsafe_fp_pl, wrong_no_2},
- /* End of REDUCE specialities */
- {"ceiling", Lceiling, Lceiling_2, wrong_no_1},
- {"floor", Lfloor, Lfloor_2, wrong_no_1},
- {"round", Lround, Lround_2, wrong_no_1},
- {"truncate", Ltruncate, Ltruncate_2, wrong_no_1},
- #ifdef COMMON
- {"boole", wrong_no_na, wrong_no_nb, Lboole},
- {"byte", too_few_2, Lbyte, wrong_no_2},
- {"byte-position", Lbyte_position, too_many_1, wrong_no_1},
- {"byte-size", Lbyte_size, too_many_1, wrong_no_1},
- {"complex", Lcomplex_1, Lcomplex_2, wrong_no_2},
- {"conjugate", Lconjugate, too_many_1, wrong_no_1},
- {"decode-float", Ldecode_float, too_many_1, wrong_no_1},
- {"float-denormalized-p", Lfloat_denormalized_p, too_many_1, wrong_no_1},
- {"float-infinity-p", Lfloat_infinity_p, too_many_1, wrong_no_1},
- {"denominator", Ldenominator, too_many_1, wrong_no_1},
- {"deposit-field", wrong_no_na, wrong_no_nb, Ldeposit_field},
- {"dpb", wrong_no_na, wrong_no_nb, Ldpb},
- {"ffloor", too_few_2, Lffloor, wrong_no_2},
- {"float-digits", Lfloat_digits, too_many_1, wrong_no_1},
- {"float-precision", Lfloat_precision, too_many_1, wrong_no_1},
- {"float-radix", Lfloat_radix, too_many_1, wrong_no_1},
- {"float-sign", Lfloat_sign1, Lfloat_sign2, wrong_no_2},
- {"fround", too_few_2, Lfround, wrong_no_2},
- {"ftruncate", too_few_2, Lftruncate, wrong_no_2},
- {"gcd", Lgcd_1, Lgcd, Lgcd_n},
- {"imagpart", Limagpart, too_many_1, wrong_no_1},
- {"integer-decode-float", Linteger_decode_float, too_many_1, wrong_no_1},
- {"integer-length", Linteger_length, too_many_1, wrong_no_1},
- {"ldb", too_few_2, Lldb, wrong_no_2},
- {"ldb-test", too_few_2, Lldb_test, wrong_no_2},
- {"lcm", Llcm_1, Llcm, Llcm_n},
- {"logbitp", too_few_2, Llogbitp, wrong_no_2},
- {"logcount", Llogcount, too_many_1, wrong_no_1},
- {"logtest", too_few_2, Llogtest, wrong_no_2},
- {"mask-field", too_few_2, Lmask_field, wrong_no_2},
- {"numerator", Lnumerator, too_many_1, wrong_no_1},
- {"realpart", Lrealpart, too_many_1, wrong_no_1},
- {"scale-float", too_few_2, Lscale_float, wrong_no_2},
- #else
- {"fix", Ltruncate, too_many_1, wrong_no_1},
- {"gcdn", too_few_2, Lgcd, wrong_no_2},
- {"lcmn", too_few_2, Llcm, wrong_no_2},
- #endif
- {NULL, 0,0,0}
- };
- /* end of arith08.c */
|