arith08.c 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393
  1. /* arith08.c Copyright (C) 1990-2002 Codemist Ltd */
  2. /*
  3. * Arithmetic functions.
  4. */
  5. /*
  6. * This code may be used and modified, and redistributed in binary
  7. * or source form, subject to the "CCL Public License", which should
  8. * accompany it. This license is a variant on the BSD license, and thus
  9. * permits use of code derived from this in either open and commercial
  10. * projects: but it does require that updates to this code be made
  11. * available back to the originators of the package.
  12. * Before merging other code in with this or linking this code
  13. * with other packages or libraries please check that the license terms
  14. * of the other material are compatible with those of this.
  15. */
  16. /* Signature: 2f37a658 08-Apr-2002 */
  17. #include <stdarg.h>
  18. #include <string.h>
  19. #include <ctype.h>
  20. #include <math.h>
  21. #include <float.h>
  22. #include "machine.h"
  23. #include "tags.h"
  24. #include "cslerror.h"
  25. #include "externs.h"
  26. #include "arith.h"
  27. #include "entries.h"
  28. #ifdef TIMEOUT
  29. #include "timeout.h"
  30. #endif
  31. #ifdef COMMON
  32. static Lisp_Object MS_CDECL Lboole(Lisp_Object nil, int nargs, ...)
  33. {
  34. Lisp_Object r, op, a, b;
  35. va_list aa;
  36. argcheck(nargs, 3, "boole");
  37. va_start(aa, nargs);
  38. op = va_arg(aa, Lisp_Object);
  39. a = va_arg(aa, Lisp_Object);
  40. b = va_arg(aa, Lisp_Object);
  41. va_end(aa);
  42. switch (op)
  43. {
  44. case fixnum_of_int(boole_clr):
  45. return onevalue(fixnum_of_int(0));
  46. case fixnum_of_int(boole_and):
  47. r = logand2(a, b);
  48. break;
  49. case fixnum_of_int(boole_andc2):
  50. push(a);
  51. b = lognot(b);
  52. pop(a);
  53. errexit();
  54. r = logand2(a, b);
  55. break;
  56. case fixnum_of_int(boole_1):
  57. return onevalue(a);
  58. case fixnum_of_int(boole_andc1):
  59. push(b);
  60. a = lognot(a);
  61. pop(b);
  62. errexit();
  63. r = logand2(a, b);
  64. break;
  65. case fixnum_of_int(boole_2):
  66. return onevalue(b);
  67. case fixnum_of_int(boole_xor):
  68. r = logxor2(a, b);
  69. break;
  70. case fixnum_of_int(boole_ior):
  71. r = logior2(a, b);
  72. break;
  73. case fixnum_of_int(boole_nor):
  74. a = logior2(a, b);
  75. errexit();
  76. r = lognot(a);
  77. break;
  78. case fixnum_of_int(boole_eqv):
  79. r = logeqv2(a, b);
  80. break;
  81. case fixnum_of_int(boole_c2):
  82. r = lognot(b);
  83. break;
  84. case fixnum_of_int(boole_orc2):
  85. b = lognot(b);
  86. errexit();
  87. r = logior2(a, b);
  88. break;
  89. case fixnum_of_int(boole_c1):
  90. r = lognot(a);
  91. break;
  92. case fixnum_of_int(boole_orc1):
  93. push(b);
  94. a = lognot(a);
  95. pop(b);
  96. errexit();
  97. r = logior2(a, b);
  98. break;
  99. case fixnum_of_int(boole_nand):
  100. a = logand2(a, b);
  101. errexit();
  102. r = lognot(a);
  103. break;
  104. case fixnum_of_int(boole_set):
  105. return onevalue(fixnum_of_int(-1));
  106. default:
  107. return aerror1("bad arg for boole", op);
  108. }
  109. errexit();
  110. return onevalue(r);
  111. }
  112. static Lisp_Object Lbyte(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  113. {
  114. a = cons(a, b);
  115. errexit();
  116. return onevalue(a);
  117. }
  118. static Lisp_Object Lbyte_position(Lisp_Object nil, Lisp_Object a)
  119. {
  120. if (!consp(a)) return aerror1("byte-position", a);
  121. else return onevalue(qcdr(a));
  122. }
  123. static Lisp_Object Lbyte_size(Lisp_Object nil, Lisp_Object a)
  124. {
  125. if (!consp(a)) return aerror1("byte-size", a);
  126. else return onevalue(qcar(a));
  127. }
  128. static Lisp_Object Lcomplex_2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  129. {
  130. /* /* Need to coerce a and b to the same type here... */
  131. a = make_complex(a, b);
  132. errexit();
  133. return onevalue(a);
  134. }
  135. static Lisp_Object Lcomplex_1(Lisp_Object nil, Lisp_Object a)
  136. {
  137. /* /* Need to make zero of same type as a */
  138. a = make_complex(a, fixnum_of_int(0));
  139. errexit();
  140. return onevalue(a);
  141. }
  142. static Lisp_Object Lconjugate(Lisp_Object nil, Lisp_Object a)
  143. {
  144. if (!is_number(a)) return aerror1("conjugate", a);
  145. if (is_numbers(a) && is_complex(a))
  146. { Lisp_Object r = real_part(a),
  147. i = imag_part(a);
  148. push(r);
  149. i = negate(i);
  150. pop(r);
  151. errexit();
  152. a = make_complex(r, i);
  153. errexit();
  154. return onevalue(a);
  155. }
  156. else return onevalue(a);
  157. }
  158. static Lisp_Object Ldecode_float(Lisp_Object nil, Lisp_Object a)
  159. {
  160. double d = float_of_number(a), neg = 1.0;
  161. int x;
  162. Lisp_Object sign;
  163. if (!is_float(a)) return aerror("decode-float");
  164. if (d < 0.0) d = -d, neg = -1.0;
  165. if (d == 0.0) x = 0;
  166. else
  167. { d = frexp(d, &x);
  168. if (d == 1.0) d = 0.5, x++;
  169. }
  170. if (is_sfloat(a)) sign = make_sfloat(neg);
  171. else sign = make_boxfloat(neg, type_of_header(flthdr(a)));
  172. errexit();
  173. push(sign);
  174. if (is_sfloat(a)) a = make_sfloat(d);
  175. else a = make_boxfloat(d, type_of_header(flthdr(a)));
  176. pop(sign);
  177. errexit();
  178. mv_2 = fixnum_of_int(x);
  179. mv_3 = sign;
  180. return nvalues(a, 3);
  181. }
  182. /*
  183. * The next two functions depend on IEEE-format floating point numbers.
  184. * They are (thus?) potentially a portability trap, but may suffice for
  185. * MOST systems. I need to test the handling of double precision values
  186. * on computers that store the two words of a double in each of the
  187. * possible orders. If the exponent field in floats was not stored in the
  188. * position that would be 0x7f800000 in an integer my treatment of short
  189. * floats would fail, so I have already assumed that that is so. I think.
  190. */
  191. static Lisp_Object Lfloat_denormalized_p(Lisp_Object nil, Lisp_Object a)
  192. {
  193. int x = 0;
  194. switch ((int)a & TAG_BITS)
  195. {
  196. #ifdef COMMON
  197. case TAG_SFLOAT:
  198. if ((a & 0x7fffffff) == TAG_SFLOAT) return onevalue(nil); /* 0.0 */
  199. x = (int32)a & 0x7f800000;
  200. return onevalue(x == 0 ? lisp_true : nil);
  201. #endif
  202. case TAG_BOXFLOAT:
  203. switch (type_of_header(flthdr(a)))
  204. {
  205. #ifdef COMMON
  206. case TYPE_SINGLE_FLOAT:
  207. if (single_float_val(a) == 0.0) return onevalue(nil);
  208. x = ((Single_Float *)((char *)a-TAG_BOXFLOAT))->f.i & 0x7f800000;
  209. return onevalue(x == 0 ? lisp_true : nil);
  210. case TYPE_LONG_FLOAT:
  211. if (long_float_val(a) == 0.0) return onevalue(nil);
  212. x = ((Long_Float *)((char *)a-TAG_BOXFLOAT)
  213. )->f.i[current_fp_rep&FP_WORD_ORDER ? 0 : 1] & 0x7ff00000;
  214. return onevalue(x == 0 ? lisp_true : nil);
  215. #endif
  216. case TYPE_DOUBLE_FLOAT:
  217. if (double_float_val(a) == 0.0) return onevalue(nil);
  218. x = ((Double_Float *)((char *)a-TAG_BOXFLOAT)
  219. )->f.i[current_fp_rep&FP_WORD_ORDER ? 0 : 1] & 0x7ff00000;
  220. return onevalue(x == 0 ? lisp_true : nil);
  221. }
  222. default:
  223. break;
  224. }
  225. return onevalue(nil);
  226. }
  227. static Lisp_Object Lfloat_infinity_p(Lisp_Object nil, Lisp_Object a)
  228. {
  229. /*
  230. * The issue of NaN values is one I do not want to worry about at present.
  231. * I deem anything with the largest possibl exponent value to be infinite.
  232. */
  233. int x = 0;
  234. switch ((int)a & TAG_BITS)
  235. {
  236. #ifdef COMMON
  237. case TAG_SFLOAT:
  238. x = (int32)a & 0x7f800000;
  239. return onevalue(x == 0x7f800000 ? lisp_true : nil);
  240. #endif
  241. case TAG_BOXFLOAT:
  242. switch (type_of_header(flthdr(a)))
  243. {
  244. #ifdef COMMON
  245. case TYPE_SINGLE_FLOAT:
  246. if (single_float_val(a) == 0.0) return onevalue(nil);
  247. x = ((Single_Float *)((char *)a-TAG_BOXFLOAT))->f.i & 0x7f800000;
  248. return onevalue(x == 0x7f800000 ? lisp_true : nil);
  249. case TYPE_LONG_FLOAT:
  250. if (long_float_val(a) == 0.0) return onevalue(nil);
  251. x = ((Long_Float *)((char *)a-TAG_BOXFLOAT)
  252. )->f.i[current_fp_rep&FP_WORD_ORDER ? 0 : 1] & 0x7ff00000;
  253. return onevalue(x == 0x7ff00000 ? lisp_true : nil);
  254. #endif
  255. case TYPE_DOUBLE_FLOAT:
  256. if (double_float_val(a) == 0.0) return onevalue(nil);
  257. x = ((Double_Float *)((char *)a-TAG_BOXFLOAT)
  258. )->f.i[current_fp_rep&FP_WORD_ORDER ? 0 : 1] & 0x7ff00000;
  259. return onevalue(x == 0x7ff00000 ? lisp_true : nil);
  260. }
  261. default:
  262. break;
  263. }
  264. return onevalue(nil);
  265. }
  266. static Lisp_Object Ldenominator(Lisp_Object nil, Lisp_Object a)
  267. {
  268. CSL_IGNORE(nil);
  269. if (!is_number(a)) return aerror1("denominator", a);
  270. if (is_numbers(a) && is_ratio(a))
  271. return onevalue(denominator(a));
  272. else return onevalue(fixnum_of_int(1));
  273. }
  274. static Lisp_Object MS_CDECL Ldeposit_field(Lisp_Object nil, int nargs, ...)
  275. {
  276. va_list aa;
  277. Lisp_Object a, b, c;
  278. CSL_IGNORE(nil);
  279. CSL_IGNORE(nargs);
  280. va_start(aa, nargs);
  281. a = va_arg(aa, Lisp_Object);
  282. b = va_arg(aa, Lisp_Object);
  283. c = va_arg(aa, Lisp_Object);
  284. va_end(aa);
  285. return aerror("deposit-field");
  286. }
  287. static Lisp_Object MS_CDECL Ldpb(Lisp_Object nil, int nargs, ...)
  288. {
  289. va_list aa;
  290. Lisp_Object a, b, c;
  291. CSL_IGNORE(nil);
  292. CSL_IGNORE(nargs);
  293. va_start(aa, nargs);
  294. a = va_arg(aa, Lisp_Object);
  295. b = va_arg(aa, Lisp_Object);
  296. c = va_arg(aa, Lisp_Object);
  297. va_end(aa);
  298. return aerror("dpb");
  299. }
  300. static Lisp_Object Lffloor(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  301. {
  302. CSL_IGNORE(nil);
  303. CSL_IGNORE(a);
  304. CSL_IGNORE(b);
  305. return aerror("ffloor");
  306. }
  307. /*
  308. * The functions such as float-digits, float-precision, float-radix are
  309. * coded here assuming that IEEE-style arithmetic is being used. If this is
  310. * not so then all the code in this file needs review. Furthermore I will
  311. * be lazy about NaNs and denormalised numbers for now and come back to
  312. * worry about them later on if I am really forced to.
  313. */
  314. static Lisp_Object Lfloat_digits(Lisp_Object nil, Lisp_Object a)
  315. {
  316. int tag = (int)a & TAG_BITS;
  317. CSL_IGNORE(nil);
  318. switch (tag)
  319. {
  320. #ifdef COMMON
  321. case TAG_SFLOAT:
  322. return onevalue(fixnum_of_int(20));
  323. #endif
  324. case TAG_BOXFLOAT:
  325. switch (type_of_header(flthdr(a)))
  326. {
  327. #ifdef COMMON
  328. case TYPE_SINGLE_FLOAT:
  329. return onevalue(fixnum_of_int(24));
  330. #endif
  331. default:
  332. return onevalue(fixnum_of_int(53));
  333. }
  334. default:
  335. return aerror("float-digits");
  336. }
  337. }
  338. static Lisp_Object Lfloat_precision(Lisp_Object nil, Lisp_Object a)
  339. {
  340. int tag = (int)a & TAG_BITS;
  341. double d = float_of_number(a);
  342. CSL_IGNORE(nil);
  343. if (d == 0.0) return onevalue(fixnum_of_int(0));
  344. /* /* I do not cope with de-normalised numbers here */
  345. switch (tag)
  346. {
  347. #ifdef COMMON
  348. case TAG_SFLOAT:
  349. return onevalue(fixnum_of_int(20));
  350. #endif
  351. case TAG_BOXFLOAT:
  352. switch (type_of_header(flthdr(a)))
  353. {
  354. #ifdef COMMON
  355. case TYPE_SINGLE_FLOAT:
  356. return onevalue(fixnum_of_int(24));
  357. #endif
  358. default:
  359. return onevalue(fixnum_of_int(53));
  360. }
  361. default:
  362. return aerror("float-precision");
  363. }
  364. }
  365. static Lisp_Object Lfloat_radix(Lisp_Object nil, Lisp_Object a)
  366. {
  367. CSL_IGNORE(nil);
  368. CSL_IGNORE(a);
  369. return onevalue(fixnum_of_int(FLT_RADIX));
  370. }
  371. static Lisp_Object Lfloat_sign2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  372. {
  373. double d = float_of_number(b);
  374. CSL_IGNORE(nil);
  375. if (float_of_number(a) < 0.0) d = -d;
  376. if (is_sfloat(b)) return onevalue(make_sfloat(d));
  377. else if (!is_bfloat(b)) return aerror1("bad arg for float-sign", b);
  378. else return onevalue(make_boxfloat(d, type_of_header(flthdr(b))));
  379. }
  380. static Lisp_Object Lfloat_sign1(Lisp_Object nil, Lisp_Object a)
  381. {
  382. double d = float_of_number(a);
  383. CSL_IGNORE(nil);
  384. if (d < 0.0) d = -1.0; else d = 1.0;
  385. if (is_sfloat(a)) return onevalue(make_sfloat(d));
  386. else if (!is_bfloat(a)) return aerror1("bad arg for float-sign", a);
  387. else return onevalue(make_boxfloat(d, type_of_header(flthdr(a))));
  388. }
  389. static Lisp_Object Lfround(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  390. {
  391. CSL_IGNORE(nil);
  392. CSL_IGNORE(a);
  393. CSL_IGNORE(b);
  394. return aerror("fround");
  395. }
  396. static Lisp_Object Lftruncate(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  397. {
  398. CSL_IGNORE(nil);
  399. CSL_IGNORE(a);
  400. CSL_IGNORE(b);
  401. return aerror("ftruncate");
  402. }
  403. Lisp_Object MS_CDECL Lgcd_n(Lisp_Object nil, int nargs, ...)
  404. {
  405. va_list a;
  406. int i;
  407. Lisp_Object r;
  408. if (nargs == 0) return fixnum_of_int(0);
  409. va_start(a, nargs);
  410. push_args(a, nargs);
  411. /*
  412. * The actual args have been passed a C args - I can not afford to
  413. * risk garbage collection until they have all been moved somewhere safe,
  414. * and here that safe place is the Lisp stack. I have to delay checking for
  415. * overflow on same until all args have been pushed.
  416. */
  417. stackcheck0(nargs);
  418. pop(r);
  419. for (i = 1; i<nargs; i++)
  420. { Lisp_Object w;
  421. if (r == fixnum_of_int(1))
  422. { popv(nargs-i);
  423. break;
  424. }
  425. pop(w);
  426. r = gcd(r, w);
  427. errexitn(nargs-i-1);
  428. }
  429. return onevalue(r);
  430. }
  431. Lisp_Object Lgcd(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  432. {
  433. a = gcd(a, b);
  434. errexit();
  435. return onevalue(a);
  436. }
  437. Lisp_Object Lgcd_1(Lisp_Object nil, Lisp_Object a)
  438. {
  439. CSL_IGNORE(nil);
  440. return onevalue(a);
  441. }
  442. static Lisp_Object Limagpart(Lisp_Object nil, Lisp_Object a)
  443. {
  444. CSL_IGNORE(nil);
  445. if (!is_number(a)) return aerror1("imagpart", a);
  446. if (is_numbers(a) && is_complex(a))
  447. return onevalue(imag_part(a));
  448. /* /* the 0.0 returned here ought to be the same type as a has */
  449. else return onevalue(fixnum_of_int(0));
  450. }
  451. static Lisp_Object Linteger_decode_float(Lisp_Object nil, Lisp_Object a)
  452. {
  453. double d = float_of_number(a);
  454. int tag = (int)a & TAG_BITS, x, neg = 0;
  455. int32 a1, a2;
  456. CSL_IGNORE(nil);
  457. if (!is_float(a)) return aerror("integer-decode-float");
  458. if (d == 0.0)
  459. #ifdef COMMON
  460. { mv_2 = fixnum_of_int(0);
  461. mv_3 = fixnum_of_int(1);
  462. nvalues(a, 3);
  463. }
  464. #else
  465. return list3(a, fixnum_of_int(0), fixnum_of_int(1));
  466. #endif
  467. if (d < 0.0) d = -d, neg = 1;
  468. d = frexp(d, &x);
  469. if (d == 1.0) d = 0.5, x++;
  470. #ifdef COMMON
  471. if (tag == TAG_SFLOAT)
  472. { d *= TWO_20;
  473. x -= 20;
  474. a1 = (int32)d;
  475. a = fixnum_of_int(a1);
  476. }
  477. else if (tag == TAG_BOXFLOAT &&
  478. type_of_header(flthdr(a)) == TYPE_SINGLE_FLOAT)
  479. { d *= TWO_24;
  480. x -= 24;
  481. a1 = (int32)d;
  482. a = fixnum_of_int(a1);
  483. }
  484. else
  485. #endif
  486. { d *= TWO_22;
  487. a1 = (int32)d;
  488. d -= (double)a1;
  489. a2 = (int32)(d*TWO_31); /* This conversion should be exact */
  490. x -= 53;
  491. a = make_two_word_bignum(a1, a2);
  492. errexit();
  493. }
  494. #ifdef COMMON
  495. { mv_2 = fixnum_of_int(x);
  496. mv_3 = neg ? fixnum_of_int(-1) : fixnum_of_int(1);
  497. return nvalues(a, 3);
  498. }
  499. #else
  500. return list3(a, fixnum_of_int(x),
  501. neg ? fixnum_of_int(-1) : fixnum_of_int(1));
  502. #endif
  503. }
  504. static Lisp_Object Linteger_length(Lisp_Object nil, Lisp_Object a)
  505. {
  506. a = Labsval(nil, a);
  507. errexit();
  508. return Lmsd(nil, a);
  509. }
  510. static Lisp_Object Lldb(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  511. {
  512. CSL_IGNORE(nil);
  513. CSL_IGNORE(a);
  514. CSL_IGNORE(b);
  515. return aerror("ldb");
  516. }
  517. Lisp_Object MS_CDECL Llcm_n(Lisp_Object nil, int nargs, ...)
  518. {
  519. va_list a;
  520. int i;
  521. Lisp_Object r;
  522. if (nargs == 0) return onevalue(fixnum_of_int(1));
  523. va_start(a, nargs);
  524. push_args(a, nargs);
  525. stackcheck0(nargs);
  526. pop(r);
  527. for (i = 1; i<nargs; i++)
  528. { Lisp_Object w;
  529. pop(w);
  530. r = lcm(r, w);
  531. errexitn(nargs-i-1);
  532. }
  533. return onevalue(r);
  534. }
  535. Lisp_Object Llcm(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  536. {
  537. a = lcm(a, b);
  538. errexit();
  539. return onevalue(a);
  540. }
  541. Lisp_Object Llcm_1(Lisp_Object nil, Lisp_Object a)
  542. {
  543. CSL_IGNORE(nil);
  544. return onevalue(a);
  545. }
  546. static Lisp_Object Lldb_test(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  547. {
  548. CSL_IGNORE(nil);
  549. CSL_IGNORE(a);
  550. CSL_IGNORE(b);
  551. return aerror("ldb-test");
  552. }
  553. static Lisp_Object Llogbitp(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  554. {
  555. CSL_IGNORE(nil);
  556. CSL_IGNORE(a);
  557. CSL_IGNORE(b);
  558. return aerror("logbitp");
  559. }
  560. static Lisp_Object Llogcount(Lisp_Object nil, Lisp_Object a)
  561. {
  562. CSL_IGNORE(nil);
  563. CSL_IGNORE(a);
  564. return aerror("logcount");
  565. }
  566. static Lisp_Object Llogtest(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  567. {
  568. CSL_IGNORE(nil);
  569. CSL_IGNORE(a);
  570. CSL_IGNORE(b);
  571. return aerror("logtest");
  572. }
  573. static Lisp_Object Lmask_field(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  574. {
  575. CSL_IGNORE(nil);
  576. CSL_IGNORE(a);
  577. CSL_IGNORE(b);
  578. return aerror("mask-field");
  579. }
  580. static Lisp_Object Lnumerator(Lisp_Object nil, Lisp_Object a)
  581. {
  582. CSL_IGNORE(nil);
  583. if (!is_number(a)) return aerror1("numerator", a);
  584. if (is_numbers(a) && is_ratio(a))
  585. return onevalue(numerator(a));
  586. else return onevalue(a);
  587. }
  588. static Lisp_Object Lrealpart(Lisp_Object nil, Lisp_Object a)
  589. {
  590. CSL_IGNORE(nil);
  591. if (!is_number(a)) return aerror1("realpart", a);
  592. if (is_numbers(a) && is_complex(a))
  593. return onevalue(real_part(a));
  594. else return onevalue(a);
  595. }
  596. static Lisp_Object Lscale_float(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  597. {
  598. double d = float_of_number(a);
  599. CSL_IGNORE(nil);
  600. if (!is_fixnum(b)) return aerror("scale-float");
  601. d = ldexp(d, int_of_fixnum(b));
  602. if (is_sfloat(a)) return onevalue(make_sfloat(d));
  603. else if (!is_bfloat(a)) return aerror1("bad arg for scale-float", a);
  604. else return onevalue(make_boxfloat(d, type_of_header(flthdr(a))));
  605. }
  606. #else /* COMMON */
  607. Lisp_Object Lgcd(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  608. {
  609. a = gcd(a, b);
  610. errexit();
  611. return onevalue(a);
  612. }
  613. Lisp_Object Llcm(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  614. {
  615. Lisp_Object g;
  616. push2(b, a);
  617. g = gcd(a, b);
  618. errexitn(2);
  619. pop(a);
  620. a = quot2(a, g);
  621. pop(b);
  622. errexit();
  623. a = times2(a, b);
  624. errexit();
  625. return onevalue(a);
  626. }
  627. #endif /* COMMON */
  628. #define FIX_TRUNCATE 0
  629. #define FIX_ROUND 1
  630. #define FIX_FLOOR 2
  631. #define FIX_CEILING 3
  632. static Lisp_Object lisp_fix_sub(Lisp_Object a, int roundmode)
  633. /*
  634. * This converts from a double to a Lisp integer, which will
  635. * quite often have to be a bignum. No overflow is permitted - the
  636. * result can always be accurate.
  637. */
  638. {
  639. int32 a0, a1, a2, a3;
  640. int x, x1;
  641. CSLbool negative;
  642. double d = float_of_number(a);
  643. if (M2_31_1 < d && d < TWO_31)
  644. { int32 a = (int32)d;
  645. /*
  646. * If my floating point value is in the range -(2^31+1) to +2^31 (exclusive)
  647. * then when C truncates it I will get an integer in the inclusive range
  648. * from -2^31 to 2^31-1, i.e. the whole range of C 32-bit integers.
  649. * If I then apply a rounding mode other than truncation I may just have
  650. * overflow, which I have to detect specially.
  651. */
  652. int32 w;
  653. double f;
  654. switch (roundmode)
  655. {
  656. case FIX_TRUNCATE:
  657. break; /* C casts truncate, so this is OK */
  658. case FIX_ROUND:
  659. f = d - (double)a;
  660. if (f > 0.5)
  661. { if (a == 0x7fffffff) return make_two_word_bignum(1, 0);
  662. else a++;
  663. }
  664. else if (f < -0.5)
  665. { if (a == ~0x7fffffff)
  666. return make_two_word_bignum(-2, 0x7fffffff);
  667. else a--;
  668. }
  669. /* The rounding rule on the next lines show what I do in 1/2ulp cases */
  670. else if (f == 0.5) a = (a+1) & ~1;
  671. else if (f == -0.5)
  672. { if (a == ~0x7fffffff)
  673. return make_two_word_bignum(-2, 0x7fffffff);
  674. else a = a & ~1;
  675. }
  676. break;
  677. case FIX_FLOOR:
  678. f = d - (double)a;
  679. if (f < 0.0)
  680. { if (a == ~0x7fffffff)
  681. return make_two_word_bignum(-2, 0x7fffffff);
  682. else a--;
  683. }
  684. break;
  685. case FIX_CEILING:
  686. f = d - (double)a;
  687. if (f > 0.0)
  688. { if (a == 0x7fffffff) return make_two_word_bignum(1, 0);
  689. else a++;
  690. }
  691. break;
  692. }
  693. w = a & fix_mask;
  694. if (w == 0 || w == fix_mask) return fixnum_of_int(a);
  695. else if (!signed_overflow(a)) return make_one_word_bignum(a);
  696. else if (a > 0) return make_two_word_bignum(0, a);
  697. else return make_two_word_bignum(-1, clear_top_bit(a));
  698. }
  699. if (d < 0.0) d = -d, negative = YES;
  700. else negative = NO;
  701. d = frexp(d, &x); /* 0.5 <= abs(d) < 1.0, x = the (binary) exponent */
  702. if (d == 1.0) d = 0.5, x++;
  703. d *= TWO_31;
  704. a1 = (int32)d; /* 2^31 > d >= 2^30 */
  705. d -= (double)a1;
  706. a2 = (unsigned32)(d*TWO_31); /* This conversion should be exact */
  707. if (negative)
  708. { if (a2 == 0) a1 = -a1;
  709. else a2 = clear_top_bit(-a2), a1 = ~a1;
  710. }
  711. x -= 62;
  712. if (x < 0) /* Need to shift right x places */
  713. { x = -x; /* The shift amount here can be 31 at most... */
  714. a3 = a2 << (32 - x);
  715. a2 = clear_top_bit((a2 >> x) | (a1 << (31 - x)));
  716. #ifdef SIGNED_SHIFTS_ARE_LOGICAL
  717. if (a1 < 0) a1 = (a1 >> x) | (((int32)-1) << (31 - x));
  718. else a1 = a1 >> x;
  719. #else
  720. a1 = a1 >> x;
  721. #endif
  722. switch (roundmode)
  723. {
  724. case FIX_TRUNCATE:
  725. if (a1 < 0 && a3 != 0) /* proper rounding on -ve values */
  726. { a2++;
  727. if (a2 < 0) /* carry */
  728. { a2 = 0;
  729. a1++;
  730. }
  731. }
  732. break;
  733. case FIX_ROUND:
  734. if ((a3 & 0x80000000U) != 0 &&
  735. (a3 != ~0x7fffffff || (a2 & 1) != 0))
  736. { a2++;
  737. if (a2 < 0) /* carry */
  738. { a2 = 0;
  739. a1++;
  740. }
  741. }
  742. break;
  743. case FIX_FLOOR: /* Comes out in wash of 2's complement */
  744. break;
  745. case FIX_CEILING:
  746. if (a3 != 0)
  747. { a2++;
  748. if (a2 < 0) /* carry */
  749. { a2 = 0;
  750. a1++;
  751. }
  752. }
  753. break;
  754. }
  755. return make_two_word_bignum(a1, a2);
  756. }
  757. /* Now the double-length value (a1,a2) is correct and exact, and it
  758. * needs shifting left by x bits. This will give a 3 or more word bignum.
  759. * Note that no rounding etc is needed at all here since there are no
  760. * fractional bits in the representation.
  761. */
  762. if (a1 < 0)
  763. { a0 = -1;
  764. a1 = clear_top_bit(a1);
  765. }
  766. else a0 = 0;
  767. x1 = x / 31;
  768. x = x % 31;
  769. a0 = (a0 << x) | (a1 >> (31-x));
  770. a1 = clear_top_bit(a1 << x) | (a2 >> (31-x));
  771. a2 = clear_top_bit(a2 << x);
  772. return make_n_word_bignum(a0, a1, a2, x1);
  773. }
  774. #ifdef COMMON
  775. static Lisp_Object lisp_fix_ratio(Lisp_Object a, int roundmode)
  776. /*
  777. * This converts from a ratio to a Lisp integer. It has to apply
  778. * the specified rounding regime.
  779. */
  780. {
  781. Lisp_Object p, q, r, nil = C_nil;;
  782. p = numerator(a);
  783. q = denominator(a);
  784. push2(q, p);
  785. r = quot2(p, q);
  786. errexitn(2);
  787. p = stack[0];
  788. stack[0] = r;
  789. p = Cremainder(p, stack[-1]);
  790. pop2(r, q);
  791. errexit();
  792. switch (roundmode)
  793. {
  794. case FIX_TRUNCATE:
  795. break;
  796. case FIX_ROUND:
  797. /* /* This case unfinished at present */
  798. break;
  799. case FIX_FLOOR:
  800. if (minusp(p))
  801. { push(r);
  802. p = plus2(p, q);
  803. pop(r);
  804. errexit();
  805. r = sub1(r);
  806. errexit();
  807. }
  808. break;
  809. case FIX_CEILING:
  810. if (plusp(p))
  811. { push(r);
  812. p = difference2(p, q);
  813. pop(r);
  814. errexit();
  815. r = add1(r);
  816. errexit();
  817. }
  818. break;
  819. }
  820. mv_2 = p;
  821. return nvalues(r, 2);
  822. }
  823. #endif
  824. static Lisp_Object lisp_fix(Lisp_Object a, int roundmode)
  825. {
  826. Lisp_Object r, nil;
  827. push(a);
  828. r = lisp_fix_sub(a, roundmode);
  829. errexitn(1);
  830. a = stack[0];
  831. stack[0] = r;
  832. a = difference2(a, r);
  833. pop(r);
  834. errexit();
  835. mv_2 = a;
  836. return nvalues(r, 2);
  837. }
  838. static Lisp_Object lisp_ifix(Lisp_Object a, Lisp_Object b, int roundmode)
  839. {
  840. Lisp_Object q, r, nil;
  841. if (is_float(a) || is_float(b))
  842. { double p = float_of_number(a), q = float_of_number(b), d = p/q;
  843. a = make_boxfloat(d, TYPE_DOUBLE_FLOAT);
  844. errexit();
  845. r = lisp_fix(a, roundmode);
  846. errexit();
  847. push(r);
  848. a = make_boxfloat(float_of_number(mv_2)*q, TYPE_DOUBLE_FLOAT);
  849. pop(r);
  850. errexit();
  851. mv_2 = a;
  852. return nvalues(r, 2);
  853. }
  854. push2(a, b);
  855. q = quot2(a, b);
  856. errexitn(2);
  857. a = stack[-1];
  858. b = stack[0];
  859. push(q);
  860. r = Cremainder(a, b);
  861. errexitn(3);
  862. switch (roundmode)
  863. {
  864. case FIX_TRUNCATE:
  865. break;
  866. case FIX_ROUND:
  867. popv(3); return aerror("two-arg ROUND");
  868. case FIX_FLOOR:
  869. if (!minusp(r)) break;
  870. r = plus2(r, stack[-1]);
  871. errexitn(3);
  872. q = stack[0];
  873. push(r);
  874. q = sub1(q);
  875. pop(r);
  876. errexitn(3);
  877. stack[0] = q;
  878. break;
  879. case FIX_CEILING:
  880. if (!plusp(r)) break;
  881. r = difference2(r, stack[-1]);
  882. errexitn(3);
  883. q = stack[0];
  884. push(r);
  885. q = add1(q);
  886. pop(r);
  887. errexitn(3);
  888. stack[0] = q;
  889. break;
  890. }
  891. pop3(q, b, a);
  892. mv_2 = r;
  893. return nvalues(q, 2);
  894. }
  895. /*
  896. * So far I have not implemented support for rational numbers in the 2-arg
  897. * versions of these functions. /*
  898. */
  899. static Lisp_Object Lceiling_2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  900. {
  901. CSL_IGNORE(nil);
  902. if (!is_number(a) || !is_number(b)) return aerror1("ceiling", a);
  903. return lisp_ifix(a, b, FIX_CEILING);
  904. }
  905. static Lisp_Object Lfloor_2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  906. {
  907. CSL_IGNORE(nil);
  908. if (!is_number(a) || !is_number(b)) return aerror1("floor", a);
  909. return lisp_ifix(a, b, FIX_FLOOR);
  910. }
  911. static Lisp_Object Lround_2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  912. {
  913. CSL_IGNORE(nil);
  914. if (!is_number(a) || !is_number(b)) return aerror1("round", a);
  915. return lisp_ifix(a, b, FIX_ROUND);
  916. }
  917. Lisp_Object Ltruncate_2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  918. {
  919. CSL_IGNORE(nil);
  920. if (!is_number(a) || !is_number(b)) return aerror1("truncate", a);
  921. return lisp_ifix(a, b, FIX_TRUNCATE);
  922. }
  923. static Lisp_Object Lceiling(Lisp_Object nil, Lisp_Object a)
  924. {
  925. CSL_IGNORE(nil);
  926. if (!is_number(a)) return aerror1("ceiling", a);
  927. #ifdef COMMON
  928. if (is_numbers(a) && is_ratio(a)) return lisp_fix_ratio(a, FIX_CEILING);
  929. #endif
  930. if (!is_float(a)) { mv_2 = fixnum_of_int(0); return nvalues(a, 2); }
  931. return lisp_fix(a, FIX_CEILING);
  932. }
  933. static Lisp_Object Lfloor(Lisp_Object nil, Lisp_Object a)
  934. {
  935. CSL_IGNORE(nil);
  936. if (!is_number(a)) return aerror1("floor", a);
  937. #ifdef COMMON
  938. if (is_numbers(a) && is_ratio(a)) return lisp_fix_ratio(a, FIX_FLOOR);
  939. #endif
  940. if (!is_float(a)) { mv_2 = fixnum_of_int(0); return nvalues(a, 2); }
  941. return lisp_fix(a, FIX_FLOOR);
  942. }
  943. static Lisp_Object Lround(Lisp_Object nil, Lisp_Object a)
  944. {
  945. CSL_IGNORE(nil);
  946. if (!is_number(a)) return aerror1("round", a);
  947. #ifdef COMMON
  948. if (is_numbers(a) && is_ratio(a)) return lisp_fix_ratio(a, FIX_ROUND);
  949. #endif
  950. if (!is_float(a)) { mv_2 = fixnum_of_int(0); return nvalues(a, 2); }
  951. return lisp_fix(a, FIX_ROUND);
  952. }
  953. Lisp_Object Ltruncate(Lisp_Object nil, Lisp_Object a)
  954. {
  955. CSL_IGNORE(nil);
  956. if (!is_number(a)) return aerror1("fix", a);
  957. #ifdef COMMON
  958. if (is_numbers(a) && is_ratio(a)) return lisp_fix_ratio(a, FIX_TRUNCATE);
  959. #endif
  960. if (!is_float(a)) { mv_2 = fixnum_of_int(0); return nvalues(a, 2); }
  961. return lisp_fix(a, FIX_TRUNCATE);
  962. }
  963. /*
  964. * The following macro is expected to select out the 32-bit word within a
  965. * floating point number that has the exponent field packed within it.
  966. * On IEEE-format machines I expect to find the exponent in the
  967. * 0x7ff00000 bits within this word.
  968. */
  969. #define top_half(d) ((int32 *)&(d))[(~current_fp_rep) & FP_WORD_ORDER]
  970. /*
  971. * symbolic procedure safe!-fp!-plus(x,y);
  972. * if zerop x then y else if zerop y then x else
  973. * begin scalar u;
  974. * if x>0.0 and y>0.0 then
  975. * if x<!!plumax and y<!!plumax then go to ret else return nil;
  976. * if x<0.0 and y<0.0 then
  977. * if -x<!!plumax and -y<!!plumax then go to ret else return nil;
  978. * if abs x<!!plumin and abs y<!!plumin then return nil;
  979. * ret: return
  980. * if (u := plus2(x,y))=0.0
  981. * or x>0.0 and y>0.0 or x<0.0 and y<0.0 then u
  982. * else if abs u<(abs x)*!!fleps1 then 0.0 else u end;
  983. */
  984. static Lisp_Object Lsafe_fp_plus(Lisp_Object env, Lisp_Object a, Lisp_Object b)
  985. /*
  986. * safe!-fp!-plus must always be given floating point arguments. In
  987. * most reasonable cases it just returns the floating point sum. If
  988. * there was some chance that the sum might either overflow or underflow
  989. * then the value NIL is returned instead. The exact place where this
  990. * function starts to report overflow is not precisely defined - all that
  991. * is guaranteed is that if a result is returned then it will be of full
  992. * precision.
  993. */
  994. {
  995. Lisp_Object nil = C_nil;
  996. double aa, bb, cc;
  997. int32 ah, bh;
  998. if (!is_float(a) || !is_float(b)) return aerror2("safe-fp-plus", a, b);
  999. /*
  1000. * I accept here that adding 0.0 to anything is always possible without
  1001. * problem.
  1002. */
  1003. if ((aa = double_float_val(a)) == 0.0) return onevalue(b);
  1004. if ((bb = double_float_val(b)) == 0.0) return onevalue(a);
  1005. if (current_fp_rep & (FP_VAXREP|FP_IBMREP))
  1006. return aerror("VAX or 370 FP rep");
  1007. ah = top_half(aa);
  1008. bh = top_half(bb);
  1009. /*
  1010. * Here I am going to assume IEEE-format numbers. I hope that I have
  1011. * picked out the word containing the exponent and that it is positioned in
  1012. * the word where I expect.
  1013. */
  1014. /*
  1015. * I deem overflow POSSIBLE if both numbers have the same sign and if at
  1016. * least one of them has an exponent 0x7fe (i.e. the highest exponent that
  1017. * a non-infinite number can have).
  1018. */
  1019. if (ah >= 0)
  1020. { if (bh >= 0)
  1021. { if (ah >= 0x7fe00000 || bh >= 0x7fe00000) return onevalue(nil);
  1022. cc = aa + bb;
  1023. }
  1024. else
  1025. /*
  1026. * I deem underflow POSSIBLE if the numbers have opposite signs and BOTH
  1027. * of them have exponents less than 0x035 (which is 53 in decimal, and
  1028. * IEEE-format numbers have 53-bit mantissas. The critical case would
  1029. * be the subtraction
  1030. * (53) 1 00000000000000000000 00000000000000000000000000000001
  1031. * - (53) 1 00000000000000000000 00000000000000000000000000000000
  1032. * where you see the LSB (which is all that is left after the subtraction)
  1033. * has to be shifted left 52 bits to get to the position of the implied
  1034. * leading 1 bit in the mantissa. As that happens 52 gets subtracted
  1035. * from the exponent, leaving it as 1, the smallest exponent for a normalised
  1036. * non-zero value.
  1037. */
  1038. { double eps, ra;
  1039. bh &= 0x7fffffff;
  1040. if (ah < 0x03500000 && bh < 0x03500000) return onevalue(nil);
  1041. /*
  1042. * The next few lines check to see if addition has led to cancellation of
  1043. * leading digits to an extent greater than !!fleps1. The environent cell
  1044. * of safe!-fp!-plus must be set to !!fleps, and then the value cell of
  1045. * this symbol is accessed to obtain the limit.
  1046. */
  1047. eps = 0.0;
  1048. if (is_symbol(env))
  1049. { Lisp_Object ve = qvalue(env);
  1050. if (is_float(ve)) eps = double_float_val(ve);
  1051. }
  1052. cc = aa + bb;
  1053. ra = cc/aa;
  1054. if (ra < 0.0) ra = -ra;
  1055. if (ra < eps) cc = 0.0; /* Force to zero if too small */
  1056. }
  1057. }
  1058. else
  1059. { if (bh >= 0)
  1060. { double eps, ra;
  1061. ah &= 0x7fffffff;
  1062. if (ah < 0x03500000 && bh < 0x03500000) return onevalue(nil);
  1063. eps = 0.0;
  1064. if (is_symbol(env))
  1065. { Lisp_Object ve = qvalue(env);
  1066. if (is_float(ve)) eps = double_float_val(ve);
  1067. }
  1068. cc = aa + bb;
  1069. ra = cc/aa;
  1070. if (ra < 0.0) ra = -ra;
  1071. if (ra < eps) cc = 0.0;
  1072. }
  1073. else
  1074. { ah &= 0x7fffffff;
  1075. bh &= 0x7fffffff;
  1076. if (ah >= 0x7fe00000 || bh >= 0x7fe00000) return onevalue(nil);
  1077. cc = aa + bb;
  1078. }
  1079. }
  1080. a = make_boxfloat(cc, TYPE_DOUBLE_FLOAT);
  1081. errexit();
  1082. return onevalue(a);
  1083. }
  1084. /*
  1085. * symbolic procedure safe!-fp!-times(x,y);
  1086. * if zerop x or zerop y then 0.0
  1087. * else if x=1.0 then y else if y=1.0 then x else
  1088. * begin scalar u,v; u := abs x; v := abs y;
  1089. * if u>=1.0 and u<=!!timmax then
  1090. * if v<=!!timmax then go to ret else return nil;
  1091. * if u>!!timmax then if v<=1.0 then go to ret else return nil;
  1092. * if u<1.0 and u>=!!timmin then
  1093. * if v>=!!timmin then go to ret else return nil;
  1094. * if u<!!timmin and v<1.0 then return nil;
  1095. * ret: return times2(x,y) end;
  1096. */
  1097. static Lisp_Object Lsafe_fp_times(Lisp_Object nil,
  1098. Lisp_Object a, Lisp_Object b)
  1099. /*
  1100. * safe!-fp!-times must always be given floating point arguments. In
  1101. * most reasonable cases it just returns the floating point product. If
  1102. * there was some chance that the product might either overflow or underflow
  1103. * then the value NIL is returned instead. REDUCE requires that if this
  1104. * function returns a non-overflow result than two such returned values
  1105. * can be added witjout fear of overflow, as in a*b+c*d. Hence I ought to
  1106. * report trouble slightly earlier than I might otherwise. - but REDUCE is
  1107. * being changed to remove this oddity, and it seems it could only cause
  1108. * trouble in (1.0,max)*(max, 1.0) complex multiplication, so I am not
  1109. * going to worry...
  1110. */
  1111. {
  1112. double aa, bb, cc;
  1113. int32 ah, bh;
  1114. if (!is_float(a) || !is_float(b)) return aerror2("safe-fp-times", a, b);
  1115. /*
  1116. * Multiplication by zero is handled as a special case here - doing so
  1117. * means that I do not have to worry about the special case of zero
  1118. * exponents later on, and it also avoids allocating fresh space to hold
  1119. * a new floating point zero value.
  1120. */
  1121. if ((aa = double_float_val(a)) == 0.0) return onevalue(a);
  1122. if ((bb = double_float_val(b)) == 0.0) return onevalue(b);
  1123. if (current_fp_rep & (FP_VAXREP|FP_IBMREP))
  1124. return aerror("VAX or 370 FP rep");
  1125. ah = top_half(aa);
  1126. bh = top_half(bb);
  1127. /*
  1128. * Here I am going to assume IEEE-format numbers. I hope that I have
  1129. * picked out the word containing the exponent and that it is positioned in
  1130. * the word where I expect.
  1131. */
  1132. ah = (ah >> 20) & 0x7ff;
  1133. bh = (bh >> 20) & 0x7ff;
  1134. ah = ah + bh;
  1135. /*
  1136. * I can estimate the value of the product by adding the exponents of the
  1137. * two operands.
  1138. */
  1139. if (ah < 0x400 || ah >= 0xbfd) return onevalue(nil);
  1140. cc = aa * bb;
  1141. a = make_boxfloat(cc, TYPE_DOUBLE_FLOAT);
  1142. errexit();
  1143. return onevalue(a);
  1144. }
  1145. /*
  1146. * symbolic procedure safe!-fp!-quot(x,y);
  1147. * if zerop y then rdqoterr()
  1148. * else if zerop x then 0.0 else if y=1.0 then x else
  1149. * begin scalar u,v; u := abs x; v := abs y;
  1150. * if u>=1.0 and u<=!!timmax then
  1151. * if v>=!!timmin then go to ret else return nil;
  1152. * if u>!!timmax then if v>=1.0 then go to ret else return nil;
  1153. * if u<1.0 and u>=!!timmin then
  1154. * if v<=!!timmax then go to ret else return nil;
  1155. * if u<!!timmin and v>1.0 then return nil;
  1156. * ret: return quotient(x,y) end;
  1157. */
  1158. static Lisp_Object Lsafe_fp_quot(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  1159. {
  1160. double aa, bb, cc;
  1161. int32 ah, bh;
  1162. if (!is_float(a) || !is_float(b)) return aerror2("safe-fp-quot", a, b);
  1163. if ((aa = double_float_val(a)) == 0.0) return onevalue(a);
  1164. /*
  1165. * I pass division by zero back to the general case here.
  1166. */
  1167. if ((bb = double_float_val(b)) == 0.0) return onevalue(nil);
  1168. if (current_fp_rep & (FP_VAXREP|FP_IBMREP))
  1169. return aerror("VAX or 370 FP rep");
  1170. ah = top_half(aa);
  1171. bh = top_half(bb);
  1172. ah = (ah >> 20) & 0x7ff;
  1173. bh = (bh >> 20) & 0x7ff;
  1174. ah = ah - bh;
  1175. if (ah <= -0x3fe || ah >= 0x3fe) return onevalue(nil);
  1176. cc = aa / bb;
  1177. a = make_boxfloat(cc, TYPE_DOUBLE_FLOAT);
  1178. errexit();
  1179. return onevalue(a);
  1180. }
  1181. /*
  1182. * symbolic procedure safe!-fp!-pl(x,y);
  1183. * % floating plus protect from under- and over-flows but no zero
  1184. * % result check.
  1185. * if zerop x then y else if zerop y then x
  1186. * else if x>0 and y>0 then
  1187. * if x<!!plumax and y<!!plumax then plus2(x,y) else nil
  1188. * else if x<0 and y<0 then
  1189. * if (-x<!!plumax and -y<!!plumax) then plus2(x,y) else nil
  1190. * else if abs x<!!plumin or abs y<!!plumin then nil else plus2(x,y);
  1191. */
  1192. static Lisp_Object Lsafe_fp_pl(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  1193. {
  1194. double aa, bb, cc;
  1195. int32 ah, bh;
  1196. if (!is_float(a) || !is_float(b)) return aerror2("safe-fp-pl", a, b);
  1197. if ((aa = double_float_val(a)) == 0.0) return onevalue(b);
  1198. if ((bb = double_float_val(b)) == 0.0) return onevalue(a);
  1199. if (current_fp_rep & (FP_VAXREP|FP_IBMREP))
  1200. return aerror("VAX or 370 FP rep");
  1201. ah = top_half(aa);
  1202. bh = top_half(bb);
  1203. if (ah >= 0)
  1204. { if (bh >= 0)
  1205. { if (ah >= 0x7fe00000 || bh >= 0x7fe00000) return onevalue(nil);
  1206. }
  1207. else
  1208. { bh &= 0x7fffffff;
  1209. if (ah < 0x03500000 && bh < 0x03500000) return onevalue(nil);
  1210. }
  1211. }
  1212. else
  1213. { if (bh >= 0)
  1214. { ah &= 0x7fffffff;
  1215. if (ah < 0x03500000 && bh < 0x03500000) return onevalue(nil);
  1216. }
  1217. else
  1218. { ah &= 0x7fffffff;
  1219. bh &= 0x7fffffff;
  1220. if (ah >= 0x7fe00000 || bh >= 0x7fe00000) return onevalue(nil);
  1221. }
  1222. }
  1223. cc = aa + bb;
  1224. a = make_boxfloat(cc, TYPE_DOUBLE_FLOAT);
  1225. errexit();
  1226. return onevalue(a);
  1227. }
  1228. /*
  1229. * symbolic procedure safe!-fp!-pl0(x,y);
  1230. * % protects floating plus against under-flow only.
  1231. * if zerop x then y else if zerop y then x
  1232. * else if abs x<!!plumin and abs y<!!plumin then nil else plus2(x,y);
  1233. *
  1234. * implement as safe!-fp!-pl without MUCH loss of speed.
  1235. */
  1236. static Lisp_Object Llose_precision(Lisp_Object nil,
  1237. Lisp_Object a, Lisp_Object n)
  1238. {
  1239. double aa;
  1240. char buffer[64];
  1241. int32 nn;
  1242. if (!is_float(a) || !is_fixnum(n)) return aerror2("lose_precision", a, n);
  1243. nn = int_of_fixnum(n);
  1244. if (nn <= 0 || nn >= 20) return onevalue(a);
  1245. sprintf(buffer, "%.*g", (int)nn, double_float_val(a));
  1246. if (sscanf(buffer, "%lg", &aa) != 1) return aerror("lose-precision");
  1247. a = make_boxfloat(aa, TYPE_DOUBLE_FLOAT);
  1248. errexit();
  1249. return onevalue(a);
  1250. }
  1251. setup_type const arith08_setup[] =
  1252. {
  1253. /*
  1254. * The next few are JUST for REDUCE, but they are expected to speed up
  1255. * rounded-mode arithmetic rather a lot.
  1256. */
  1257. {"lose-precision", too_few_2, Llose_precision, wrong_no_2},
  1258. {"safe-fp-plus", too_few_2, Lsafe_fp_plus, wrong_no_2},
  1259. {"safe-fp-times", too_few_2, Lsafe_fp_times, wrong_no_2},
  1260. {"safe-fp-quot", too_few_2, Lsafe_fp_quot, wrong_no_2},
  1261. {"safe-fp-pl", too_few_2, Lsafe_fp_pl, wrong_no_2},
  1262. {"safe-fp-pl0", too_few_2, Lsafe_fp_pl, wrong_no_2},
  1263. /* End of REDUCE specialities */
  1264. {"ceiling", Lceiling, Lceiling_2, wrong_no_1},
  1265. {"floor", Lfloor, Lfloor_2, wrong_no_1},
  1266. {"round", Lround, Lround_2, wrong_no_1},
  1267. {"truncate", Ltruncate, Ltruncate_2, wrong_no_1},
  1268. #ifdef COMMON
  1269. {"boole", wrong_no_na, wrong_no_nb, Lboole},
  1270. {"byte", too_few_2, Lbyte, wrong_no_2},
  1271. {"byte-position", Lbyte_position, too_many_1, wrong_no_1},
  1272. {"byte-size", Lbyte_size, too_many_1, wrong_no_1},
  1273. {"complex", Lcomplex_1, Lcomplex_2, wrong_no_2},
  1274. {"conjugate", Lconjugate, too_many_1, wrong_no_1},
  1275. {"decode-float", Ldecode_float, too_many_1, wrong_no_1},
  1276. {"float-denormalized-p", Lfloat_denormalized_p, too_many_1, wrong_no_1},
  1277. {"float-infinity-p", Lfloat_infinity_p, too_many_1, wrong_no_1},
  1278. {"denominator", Ldenominator, too_many_1, wrong_no_1},
  1279. {"deposit-field", wrong_no_na, wrong_no_nb, Ldeposit_field},
  1280. {"dpb", wrong_no_na, wrong_no_nb, Ldpb},
  1281. {"ffloor", too_few_2, Lffloor, wrong_no_2},
  1282. {"float-digits", Lfloat_digits, too_many_1, wrong_no_1},
  1283. {"float-precision", Lfloat_precision, too_many_1, wrong_no_1},
  1284. {"float-radix", Lfloat_radix, too_many_1, wrong_no_1},
  1285. {"float-sign", Lfloat_sign1, Lfloat_sign2, wrong_no_2},
  1286. {"fround", too_few_2, Lfround, wrong_no_2},
  1287. {"ftruncate", too_few_2, Lftruncate, wrong_no_2},
  1288. {"gcd", Lgcd_1, Lgcd, Lgcd_n},
  1289. {"imagpart", Limagpart, too_many_1, wrong_no_1},
  1290. {"integer-decode-float", Linteger_decode_float, too_many_1, wrong_no_1},
  1291. {"integer-length", Linteger_length, too_many_1, wrong_no_1},
  1292. {"ldb", too_few_2, Lldb, wrong_no_2},
  1293. {"ldb-test", too_few_2, Lldb_test, wrong_no_2},
  1294. {"lcm", Llcm_1, Llcm, Llcm_n},
  1295. {"logbitp", too_few_2, Llogbitp, wrong_no_2},
  1296. {"logcount", Llogcount, too_many_1, wrong_no_1},
  1297. {"logtest", too_few_2, Llogtest, wrong_no_2},
  1298. {"mask-field", too_few_2, Lmask_field, wrong_no_2},
  1299. {"numerator", Lnumerator, too_many_1, wrong_no_1},
  1300. {"realpart", Lrealpart, too_many_1, wrong_no_1},
  1301. {"scale-float", too_few_2, Lscale_float, wrong_no_2},
  1302. #else
  1303. {"fix", Ltruncate, too_many_1, wrong_no_1},
  1304. {"gcdn", too_few_2, Lgcd, wrong_no_2},
  1305. {"lcmn", too_few_2, Llcm, wrong_no_2},
  1306. #endif
  1307. {NULL, 0,0,0}
  1308. };
  1309. /* end of arith08.c */