arith06.c 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754
  1. /* arith06.c Copyright (C) 1990-99 Codemist Ltd */
  2. /*
  3. * Arithmetic functions... lots of Lisp entrypoints.
  4. * note that for CSL I want plus and times to be special forms.
  5. */
  6. /* Signature: 787eef23 07-Mar-2000 */
  7. #include <stdarg.h>
  8. #include <string.h>
  9. #include <ctype.h>
  10. #include <math.h>
  11. #include "machine.h"
  12. #include "tags.h"
  13. #include "cslerror.h"
  14. #include "externs.h"
  15. #include "arith.h"
  16. #include "entries.h"
  17. #ifdef TIMEOUT
  18. #include "timeout.h"
  19. #endif
  20. /*****************************************************************************/
  21. /*** Lisp-callable versions of arithmetic functions ***/
  22. /*****************************************************************************/
  23. Lisp_Object Ladd1(Lisp_Object nil, Lisp_Object a)
  24. {
  25. if (is_fixnum(a))
  26. { unsigned32 r = (unsigned32)a + 0x10;
  27. /* fixnums have data shifted left 4 bits */
  28. if (r == ~0x7ffffffe) /* The ONLY possible overflow case here */
  29. a = make_one_word_bignum(1 + int_of_fixnum(a));
  30. else return onevalue((Lisp_Object)r); /* the cheap case */
  31. }
  32. else a = plus2(a, fixnum_of_int(1));
  33. errexit();
  34. return onevalue(a);
  35. }
  36. Lisp_Object Lsub1(Lisp_Object nil, Lisp_Object a)
  37. {
  38. if (is_fixnum(a))
  39. { if (a == ~0x7ffffffe) /* The ONLY possible overflow case here */
  40. return make_one_word_bignum(int_of_fixnum(a) - 1);
  41. else return onevalue((Lisp_Object)(a - 0x10));
  42. }
  43. else a = plus2(a, fixnum_of_int(-1));
  44. errexit();
  45. return onevalue(a);
  46. }
  47. #ifdef COMMON
  48. Lisp_Object Lfloat_2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  49. {
  50. CSL_IGNORE(nil);
  51. if (is_sfloat(b))
  52. { double d = float_of_number(a);
  53. return onevalue(make_sfloat(d));
  54. }
  55. else if (!is_bfloat(b)) return aerror1("bad arg for float", b);
  56. else
  57. { double d = float_of_number(a);
  58. return onevalue(make_boxfloat(d, type_of_header(flthdr(b))));
  59. }
  60. }
  61. #endif
  62. Lisp_Object Lfloat(Lisp_Object nil, Lisp_Object a)
  63. {
  64. double d;
  65. CSL_IGNORE(nil);
  66. if (!is_number(a)) return aerror1("bad arg for float", a);
  67. d = float_of_number(a);
  68. #ifdef COMMON
  69. /* Do we REALLY want single precision by default here? */
  70. return onevalue(make_boxfloat(d, TYPE_SINGLE_FLOAT));
  71. #else
  72. return onevalue(make_boxfloat(d, TYPE_DOUBLE_FLOAT));
  73. #endif
  74. }
  75. Lisp_Object Llognot(Lisp_Object nil, Lisp_Object a)
  76. {
  77. a = lognot(a);
  78. errexit();
  79. return onevalue(a);
  80. }
  81. Lisp_Object Lash(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  82. {
  83. a = ash(a, b);
  84. errexit();
  85. return onevalue(a);
  86. }
  87. Lisp_Object Lash1(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  88. /*
  89. * This function multiplies or divides by a power of two. Note that
  90. * this corresponds to natural shifts on a sign-and-magnitude machine,
  91. * but is not an "arithmetic" shift as that term is understood on
  92. * 2's complement machines.
  93. */
  94. {
  95. CSLbool negative = NO;
  96. if (!is_fixnum(b)) return aerror("ash1");
  97. if (minusp(a))
  98. { negative = YES;
  99. a = negate(a);
  100. }
  101. errexit();
  102. a = ash(a, b);
  103. errexit();
  104. if (negative)
  105. { a = negate(a);
  106. errexit();
  107. }
  108. return onevalue(a);
  109. }
  110. static int msd_table[256] =
  111. {
  112. 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
  113. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
  114. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  115. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  116. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  117. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  118. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  119. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  120. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  121. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  122. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  123. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  124. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  125. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  126. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  127. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
  128. };
  129. Lisp_Object Lmsd(Lisp_Object nil, Lisp_Object a)
  130. {
  131. int32 top;
  132. int32 r = 0;
  133. CSL_IGNORE(nil);
  134. if (is_fixnum(a)) top = int_of_fixnum(a);
  135. else if (is_numbers(a))
  136. { Header h = numhdr(a);
  137. if (!is_bignum_header(h)) return aerror1("bad arg for msd", a);
  138. r = length_of_header(h)/4 - 2;
  139. top = bignum_digits(a)[r];
  140. r = 31*r;
  141. }
  142. else return aerror1("bad arg for msd", a);
  143. if (top < 0) return aerror1("negative arg for msd", a); /* -ve arg */
  144. /*
  145. * Note that top may be zero here, but in that case the next word down of
  146. * the bignum involved MUST be fully normalised with its top bit set.
  147. * The effect of this code is that I return (msd 0) => 0.
  148. */
  149. if (top >= 0x10000) r += 16, top >>= 16;
  150. if (top >= 0x100) r += 8, top >>= 8;
  151. return onevalue(fixnum_of_int(r + msd_table[top]));
  152. }
  153. static int lsd_table[256] =
  154. {
  155. 8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  156. 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  157. 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  158. 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  159. 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  160. 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  161. 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  162. 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  163. 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  164. 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  165. 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  166. 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  167. 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  168. 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  169. 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  170. 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
  171. };
  172. Lisp_Object Llsd(Lisp_Object nil, Lisp_Object a)
  173. {
  174. int32 top;
  175. int32 r = 0;
  176. CSL_IGNORE(nil);
  177. if (is_fixnum(a))
  178. { top = int_of_fixnum(a);
  179. /* lsd(0) is taken to have the value 0 here - it is a bit of an odd case */
  180. if (top == 0) return onevalue(a);
  181. }
  182. else if (is_numbers(a))
  183. { Header h = numhdr(a);
  184. if (!is_bignum_header(h)) return aerror1("bad arg for lsd", a);
  185. while ((top = bignum_digits(a)[r]) == 0) r++;
  186. r = 31*r;
  187. }
  188. else return aerror1("bad arg for lsd", a);
  189. if (top < 0) return aerror1("negative arg for lsd", a); /* -ve arg */
  190. /* top is non-zero here */
  191. if ((top & 0xffffu) == 0) r += 16, top >>= 16;
  192. if ((top & 0xff) == 0) r += 8, top >>= 8;
  193. return onevalue(fixnum_of_int(r + lsd_table[top & 0xff]));
  194. }
  195. Lisp_Object Linorm(Lisp_Object nil, Lisp_Object a, Lisp_Object k)
  196. /*
  197. * This is a piece of magic especially designed to speed up the
  198. * REDUCE big-float code. It adjusts the integer a until it has
  199. * just k bits, and returns a correction to the associated exponent.
  200. * It combines aspects of msd, lsd, ash and a rounding operation.
  201. */
  202. {
  203. int32 top, bottom, kk, bits;
  204. int32 rtop = 0, rbottom = 0;
  205. CSLbool was_fixnum = NO, was_negative = NO, round_up;
  206. if (is_fixnum(k) && (int32)k >= 0) kk = int_of_fixnum(k);
  207. else return aerror1("bad args for inorm", k);
  208. if (is_fixnum(a))
  209. { top = int_of_fixnum(a);
  210. if (top == 0) return aerror1("zero arg for inorm", a);
  211. bottom = top;
  212. was_fixnum = YES;
  213. }
  214. else if (is_numbers(a))
  215. { Header h = numhdr(a);
  216. if (!is_bignum_header(h)) return aerror1("bad arg for inorm", a);
  217. rtop = length_of_header(h)/4 - 2;
  218. top = bignum_digits(a)[rtop];
  219. was_negative = (top < 0);
  220. rtop = 31*rtop;
  221. while ((bottom = bignum_digits(a)[rbottom]) == 0) rbottom++;
  222. rbottom = 31*rbottom;
  223. }
  224. else return aerror1("bad arg for inorm", a);
  225. if (top < 0) top = ~top; /* Now top is guaranteed positive */
  226. if (top >= 0x10000) rtop += 16, top >>= 16;
  227. if (top >= 0x100) rtop += 8, top >>= 8;
  228. rtop = rtop + msd_table[top];
  229. if ((bottom & 0xffffu) == 0) rbottom += 16, bottom >>= 16;
  230. if ((bottom & 0xff) == 0) rbottom += 8, bottom >>= 8;
  231. rbottom = rbottom + lsd_table[bottom & 0xff];
  232. /*
  233. * The next line adjusts for the odd case where the input number is
  234. * minus an exact power of 2, in which case finding its most significant bit
  235. * involved just a little correction.
  236. */
  237. round_up = was_negative;
  238. if (rtop == rbottom) rtop++;
  239. bits = rtop - rbottom; /* bits used in the number */
  240. if (bits <= kk) kk = rbottom; /* no rounding wanted */
  241. else if (was_fixnum)
  242. { int bit;
  243. /*
  244. * If the input was a fixnum and I need to decrease its precision
  245. * I will do it in-line here, mainly so that the bignum code that comes
  246. * later will not have to worry so much about the possibility of having
  247. * any fixnums around.
  248. */
  249. kk = rtop - kk;
  250. bit = ((int32)1) << (kk - 1);
  251. top = int_of_fixnum(a);
  252. if (top < 0)
  253. { top = -top;
  254. /*
  255. * It is almost the case that for negative values I should round if the
  256. * bit I want to test is a zero (rather than a 1), but this is not true when
  257. * the bit involved is the least significant set bit in the word. So to
  258. * keep it simple I negate, test, adjust and negate back when working with
  259. * single precision numbers. I also do the shifting right on the positive
  260. * value to avoid problems with the bits that get shifted off, and with
  261. * computers where right shifts are logical rather than arithmetic.
  262. */
  263. if ((top & bit) != 0) top += bit;
  264. top = top >> kk;
  265. top = -top;
  266. }
  267. else
  268. { if ((top & bit) != 0) top += bit;
  269. top = top >> kk;
  270. }
  271. /*
  272. * All the shifts I do here move only zero bits off the bottom of the
  273. * word, and so there are no issues about +ve vs -ve numbers to bother me.
  274. */
  275. while ((top & 0xf) == 0)
  276. { top = top >> 4;
  277. #ifdef SIGNED_SHIFTS_ARE_LOGICAL
  278. if (top & 0x08000000) top |= ~0x0fffffff;
  279. #endif
  280. kk += 4;
  281. }
  282. while ((top & 0x1) == 0)
  283. { top = top >> 1;
  284. #ifdef SIGNED_SHIFTS_ARE_LOGICAL
  285. if (top & 0x40000000) top |= ~0x7fffffff;
  286. #endif
  287. kk += 1;
  288. }
  289. a = cons(fixnum_of_int(top), fixnum_of_int(kk));
  290. errexit();
  291. return onevalue(a);
  292. }
  293. else
  294. { int32 wk, bk;
  295. /*
  296. * Here my input was a bignum and I have established that I not only need
  297. * to shift it right but that I will need to lose some non-zero digits from
  298. * the right hand end. To cope with this I need to decide whether it will
  299. * round up or down, and then perform the appropriate shifts, including a
  300. * post-normalisation to ensure that the mantissa of the number as returned
  301. * is odd.
  302. */
  303. kk = rtop - kk;
  304. if (rbottom == kk-1) round_up = YES;
  305. else
  306. { int32 wk1 = (kk-1) / 31, bk1 = (kk-1) % 31;
  307. int32 bit = ((int32)1) << bk1;
  308. round_up = ((bit & bignum_digits(a)[wk1]) != 0);
  309. if (was_negative) round_up = !round_up;
  310. }
  311. /*
  312. * Now I need to find out how much I will need to shift AFTER rounding
  313. * and truncation to leave me with a properly normalised value.
  314. */
  315. wk = kk / 31, bk = kk % 31;
  316. /*
  317. * If I have a positive value that is not being rounded up I want to skip
  318. * over 0 bits until I find a 1. Similarly for a negative value that is
  319. * being rounded up.
  320. */
  321. if (was_negative == round_up)
  322. {
  323. for (;;)
  324. { int32 bit = ((int32)1) << bk;
  325. if ((bignum_digits(a)[wk] & bit) != 0) break;
  326. kk++;
  327. bk++;
  328. if (bk == 31) bk = 0, wk++;
  329. }
  330. }
  331. else
  332. /*
  333. * A positive value that is being rounded up or a negative one that is not
  334. * should cause me to skip over 1 bits until I find a 0. The 0 I find
  335. * will be promoted into a 1 achieve the rounding I need.
  336. */
  337. {
  338. for (;;)
  339. { int32 bit = ((int32)1) << bk;
  340. if ((bignum_digits(a)[wk] & bit) == 0) break;
  341. kk++;
  342. bk++;
  343. if (bk == 31) bk = 0, wk++;
  344. }
  345. }
  346. }
  347. if (kk != 0)
  348. { a = ash(a, fixnum_of_int(-kk));
  349. errexit();
  350. /*
  351. * All the adjustment I now need to allow for right-shifting negative
  352. * numbers and rounding off - at all reduces to just forcing the bottom bit
  353. * of the result I compute here to be a 1!
  354. */
  355. if (is_fixnum(a)) a |= 0x10;
  356. else bignum_digits(a)[0] |= 1;
  357. }
  358. a = cons(a, fixnum_of_int(kk));
  359. errexit();
  360. return onevalue(a);
  361. }
  362. #ifdef COMMON
  363. /*
  364. * Implemented as a special form for Standard Lisp. Must be a regular
  365. * function in Common Lisp.
  366. */
  367. static Lisp_Object MS_CDECL Lplus(Lisp_Object nil, int nargs, ...)
  368. /*
  369. * This adds up a whole bunch of numbers together.
  370. * (+ a1 a2 a3 a4 a5) is computed as
  371. * (+ a1 (+ a2 (* a3 (+ a4 a5))))
  372. */
  373. {
  374. va_list a;
  375. int i;
  376. Lisp_Object r;
  377. if (nargs == 0) return fixnum_of_int(0);
  378. va_start(a, nargs);
  379. push_args(a, nargs);
  380. /*
  381. * The actual args have been passed a C args - I can not afford to
  382. * risk garbage collection until they have all been moved somewhere safe,
  383. * and here that safe place is the Lisp stack. I have to delay checking for
  384. * overflow on same until all args have been pushed.
  385. */
  386. stackcheck0(nargs);
  387. pop(r);
  388. nil = C_nil;
  389. for (i = 1; i<nargs; i++)
  390. { Lisp_Object w;
  391. pop(w);
  392. if (is_fixnum(r) && is_fixnum(w))
  393. { int32 c = int_of_fixnum(r) + int_of_fixnum(w);
  394. int32 w1 = c & fix_mask;
  395. if (w1 == 0 || w1 == fix_mask)
  396. { r = fixnum_of_int(c);
  397. continue;
  398. }
  399. }
  400. r = plus2(r, w);
  401. errexitn(nargs-i);
  402. }
  403. return onevalue(r);
  404. }
  405. static Lisp_Object MS_CDECL Ldifference(Lisp_Object nil, int nargs, ...)
  406. {
  407. va_list a;
  408. Lisp_Object r;
  409. int i;
  410. if (nargs == 0) return onevalue(fixnum_of_int(0));
  411. va_start(a, nargs);
  412. push_args(a, nargs);
  413. stackcheck0(nargs);
  414. nil = C_nil;
  415. if (nargs == 1)
  416. { pop(r);
  417. r = negate(r);
  418. errexit();
  419. return onevalue(r);
  420. }
  421. r = stack[1-nargs];
  422. /*
  423. * (- a1 a2 a3 a4) is computed as
  424. * (((a1 - a4) - a3) - a2) which does not seem too bad here.
  425. */
  426. for (i=1; i<nargs; i++)
  427. { Lisp_Object w;
  428. pop(w);
  429. r = difference2(r, w);
  430. errexitn(nargs-i);
  431. }
  432. popv(1);
  433. return onevalue(r);
  434. }
  435. static Lisp_Object MS_CDECL Ltimes(Lisp_Object nil, int nargs, ...)
  436. /*
  437. * This multiplies a whole bunch of numbers together.
  438. */
  439. {
  440. va_list a;
  441. int i;
  442. Lisp_Object r;
  443. if (nargs == 0) return fixnum_of_int(1);
  444. va_start(a, nargs);
  445. push_args(a, nargs);
  446. stackcheck0(nargs);
  447. pop(r);
  448. nil = C_nil;
  449. for (i=1; i<nargs; i++)
  450. { Lisp_Object w;
  451. pop(w);
  452. r = times2(r, w);
  453. errexitn(nargs-i);
  454. }
  455. return onevalue(r);
  456. }
  457. Lisp_Object MS_CDECL Lquotient_n(Lisp_Object nil, int nargs, ...)
  458. {
  459. va_list a;
  460. Lisp_Object r;
  461. int i;
  462. if (nargs == 0) return onevalue(fixnum_of_int(1));
  463. va_start(a, nargs);
  464. push_args(a, nargs);
  465. stackcheck0(nargs);
  466. if (nargs == 1)
  467. { pop(r);
  468. r = CLquot2(fixnum_of_int(1), r);
  469. errexit();
  470. return onevalue(r);
  471. }
  472. r = stack[1-nargs];
  473. for (i=1; i<nargs; i++)
  474. { Lisp_Object w;
  475. pop(w);
  476. r = CLquot2(r, w);
  477. errexitn(nargs-i);
  478. }
  479. popv(1);
  480. return onevalue(r);
  481. }
  482. Lisp_Object Lquotient(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  483. {
  484. a = CLquot2(a, b);
  485. errexit();
  486. return onevalue(a);
  487. }
  488. static Lisp_Object LSLquotient(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  489. {
  490. a = quot2(a, b);
  491. errexit();
  492. return onevalue(a);
  493. }
  494. Lisp_Object Lquotient_1(Lisp_Object nil, Lisp_Object b)
  495. {
  496. b = CLquot2(fixnum_of_int(1), b);
  497. errexit();
  498. return onevalue(b);
  499. }
  500. #else /* COMMON */
  501. Lisp_Object Lquotient(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  502. {
  503. a = quot2(a, b);
  504. errexit();
  505. return onevalue(a);
  506. }
  507. #endif /* COMMON */
  508. Lisp_Object Ldivide(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  509. {
  510. Lisp_Object q, r;
  511. stackcheck2(0, a, b);
  512. push2(a, b);
  513. q = quot2(a, b);
  514. pop2(b, a);
  515. errexit();
  516. push(q);
  517. r = Cremainder(a, b);
  518. pop(q);
  519. errexit();
  520. q = cons(q, r);
  521. errexit();
  522. return onevalue(q);
  523. }
  524. Lisp_Object Lrem(Lisp_Object nil, Lisp_Object p, Lisp_Object q)
  525. {
  526. p = Cremainder(p, q);
  527. errexit();
  528. return onevalue(p);
  529. }
  530. Lisp_Object Lmod(Lisp_Object nil, Lisp_Object p, Lisp_Object q)
  531. {
  532. p = modulus(p, q);
  533. errexit();
  534. return onevalue(p);
  535. }
  536. Lisp_Object Lplus2(Lisp_Object nil, Lisp_Object p, Lisp_Object q)
  537. {
  538. if (is_fixnum(p) && is_fixnum(q))
  539. { int32 c = int_of_fixnum(p) + int_of_fixnum(q);
  540. int32 w = c & fix_mask;
  541. if (w == 0 || w == fix_mask) return onevalue(fixnum_of_int(c));
  542. }
  543. p = plus2(p, q);
  544. errexit();
  545. return onevalue(p);
  546. }
  547. Lisp_Object Ltimes2(Lisp_Object nil, Lisp_Object p,
  548. Lisp_Object q)
  549. {
  550. p = times2(p, q);
  551. errexit();
  552. return onevalue(p);
  553. }
  554. Lisp_Object Ldifference2(Lisp_Object nil, Lisp_Object a,
  555. Lisp_Object b)
  556. {
  557. a = difference2(a, b);
  558. errexit();
  559. return onevalue(a);
  560. }
  561. Lisp_Object Lminus(Lisp_Object nil, Lisp_Object a)
  562. {
  563. a = negate(a);
  564. errexit();
  565. return onevalue(a);
  566. }
  567. typedef Lisp_Object boolopfn(Lisp_Object, Lisp_Object);
  568. static struct bfz { boolopfn *fn; Lisp_Object base; } boolop_array[] =
  569. {
  570. {0, 0},
  571. {logand2, fixnum_of_int(-1)},
  572. {0, 0},
  573. {0, 0},
  574. {0, 0},
  575. {0, 0},
  576. {logxor2, fixnum_of_int(0)},
  577. {logior2, fixnum_of_int(0)},
  578. {0, 0},
  579. {logeqv2, fixnum_of_int(-1)},
  580. {0, 0},
  581. {0, 0},
  582. {0, 0},
  583. {0, 0},
  584. {0, 0},
  585. {0, 0}
  586. };
  587. static Lisp_Object MS_CDECL Lboolfn(Lisp_Object env, int nargs, ...)
  588. {
  589. va_list a;
  590. Lisp_Object nil = C_nil, r;
  591. int i;
  592. int32 what = int_of_fixnum(env);
  593. if (nargs == 0) return onevalue(boolop_array[what].base);
  594. va_start(a, nargs);
  595. push_args(a, nargs);
  596. stackcheck0(nargs);
  597. pop(r);
  598. for (i=1; i<nargs; i++)
  599. { Lisp_Object w;
  600. pop(w);
  601. r = (*boolop_array[what].fn)(r, w);
  602. errexitn(nargs-i);
  603. }
  604. return onevalue(r);
  605. }
  606. Lisp_Object Lzerop(Lisp_Object nil, Lisp_Object a)
  607. {
  608. CSLbool fg;
  609. fg = zerop(a);
  610. errexit();
  611. return onevalue(Lispify_predicate(fg));
  612. }
  613. Lisp_Object Lonep(Lisp_Object nil, Lisp_Object a)
  614. {
  615. CSLbool fg;
  616. fg = onep(a);
  617. errexit();
  618. return onevalue(Lispify_predicate(fg));
  619. }
  620. Lisp_Object Levenp(Lisp_Object nil, Lisp_Object a)
  621. {
  622. switch ((int)a & TAG_BITS)
  623. {
  624. case TAG_FIXNUM:
  625. return onevalue(((int32)a & 0x10) == 0 ? lisp_true : nil);
  626. case TAG_NUMBERS:
  627. if (is_bignum(a))
  628. return onevalue((bignum_digits(a)[0] & 1) == 0 ? lisp_true : nil);
  629. /* else drop through */
  630. default:
  631. return aerror1("bad arg for evenp", a);
  632. }
  633. }
  634. Lisp_Object Loddp(Lisp_Object nil, Lisp_Object a)
  635. {
  636. switch ((int)a & TAG_BITS)
  637. {
  638. case TAG_FIXNUM:
  639. return onevalue(((int32)a & 0x10) != 0 ? lisp_true : nil);
  640. case TAG_NUMBERS:
  641. if (is_bignum(a))
  642. return onevalue((bignum_digits(a)[0] & 1) != 0 ? lisp_true : nil);
  643. /* else drop through */
  644. default:
  645. return aerror1("oddp", a);
  646. }
  647. }
  648. Lisp_Object Lminusp(Lisp_Object nil, Lisp_Object a)
  649. {
  650. /*
  651. * For CSL I demand (minusp <non-number>) = nil. Note that this ensures
  652. * that minusp will not fail... so nil wil be intact on the way out.
  653. */
  654. return onevalue(is_number(a) && minusp(a) ? lisp_true : nil);
  655. }
  656. Lisp_Object Lplusp(Lisp_Object nil, Lisp_Object a)
  657. {
  658. return onevalue(is_number(a) && plusp(a) ? lisp_true : nil);
  659. }
  660. /*
  661. * The next few functions take an arbitrary number of args in Common
  662. * Lisp mode but just 2 args in CSL.
  663. */
  664. #ifdef COMMON
  665. Lisp_Object MS_CDECL Leqn_n(Lisp_Object nil, int nargs, ...)
  666. {
  667. va_list a;
  668. int i;
  669. Lisp_Object r;
  670. if (nargs < 2) return onevalue(lisp_true);
  671. if (nargs > ARG_CUT_OFF) return aerror("too many args for =");
  672. va_start(a, nargs);
  673. push_args(a, nargs);
  674. stackcheck0(nargs);
  675. r = stack[1-nargs];
  676. for (i = 1; i<nargs; i++)
  677. { Lisp_Object s = stack[1+i-nargs];
  678. CSLbool w = numeq2(r, s);
  679. nil = C_nil;
  680. if (exception_pending()) { popv(nargs); return nil; }
  681. if (!w)
  682. { popv(nargs);
  683. return onevalue(nil);
  684. }
  685. r = s;
  686. }
  687. popv(nargs);
  688. return onevalue(lisp_true);
  689. }
  690. Lisp_Object Leqn(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  691. {
  692. CSLbool w = numeq2(a, b);
  693. errexit();
  694. return onevalue(w ? lisp_true : nil);
  695. }
  696. Lisp_Object Leqn_1(Lisp_Object nil, Lisp_Object a)
  697. {
  698. CSL_IGNORE(nil);
  699. CSL_IGNORE(a);
  700. return onevalue(lisp_true);
  701. }
  702. Lisp_Object MS_CDECL Llessp_n(Lisp_Object nil, int nargs, ...)
  703. {
  704. va_list a;
  705. int i;
  706. Lisp_Object r;
  707. if (nargs < 2) return onevalue(lisp_true);
  708. if (nargs > ARG_CUT_OFF) return aerror("too many args for <");
  709. va_start(a, nargs);
  710. push_args(a, nargs);
  711. stackcheck0(nargs);
  712. r = stack[1-nargs];
  713. for (i = 1; i<nargs; i++)
  714. { Lisp_Object s = stack[1+i-nargs];
  715. CSLbool w = lessp2(r, s);
  716. nil = C_nil;
  717. if (exception_pending()) { va_end(a); return nil; }
  718. if (!w)
  719. { va_end(a);
  720. return onevalue(nil);
  721. }
  722. r = s;
  723. }
  724. va_end(a);
  725. return onevalue(lisp_true);
  726. }
  727. Lisp_Object Llessp(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  728. {
  729. CSLbool w = lessp2(a, b);
  730. errexit();
  731. return onevalue(w ? lisp_true : nil);
  732. }
  733. Lisp_Object Llessp_1(Lisp_Object nil, Lisp_Object a)
  734. {
  735. CSL_IGNORE(nil);
  736. CSL_IGNORE(a);
  737. return onevalue(lisp_true);
  738. }
  739. Lisp_Object MS_CDECL Lgreaterp_n(Lisp_Object nil, int nargs, ...)
  740. {
  741. va_list a;
  742. int i;
  743. Lisp_Object r;
  744. if (nargs < 2) return onevalue(lisp_true);
  745. if (nargs > ARG_CUT_OFF) return aerror("too many args for >");
  746. va_start(a, nargs);
  747. push_args(a, nargs);
  748. stackcheck0(nargs);
  749. r = stack[1-nargs];
  750. for (i = 1; i<nargs; i++)
  751. { Lisp_Object s = stack[1+i-nargs];
  752. CSLbool w = lessp2(s, r);
  753. nil = C_nil;
  754. if (exception_pending()) { popv(nargs); return nil; }
  755. if (!w)
  756. { popv(nargs);
  757. return onevalue(nil);
  758. }
  759. r = s;
  760. }
  761. popv(nargs);
  762. return onevalue(lisp_true);
  763. }
  764. Lisp_Object Lgreaterp(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  765. {
  766. CSLbool w = lessp2(b, a);
  767. errexit();
  768. return onevalue(w ? lisp_true : nil);
  769. }
  770. Lisp_Object Lgreaterp_1(Lisp_Object nil, Lisp_Object a)
  771. {
  772. CSL_IGNORE(nil);
  773. CSL_IGNORE(a);
  774. return onevalue(lisp_true);
  775. }
  776. static Lisp_Object MS_CDECL Lneqn(Lisp_Object nil, int nargs, ...)
  777. /*
  778. * /= is supposed to check that NO pair of args match.
  779. */
  780. {
  781. int i, j;
  782. Lisp_Object *r;
  783. va_list a;
  784. if (nargs < 2) return onevalue(lisp_true);
  785. r = (Lisp_Object *)&work_1;
  786. if (nargs > ARG_CUT_OFF) return aerror("too many args for /=");
  787. va_start(a, nargs);
  788. for (i=0; i<nargs; i++) r[i] = va_arg(a, Lisp_Object);
  789. va_end(a);
  790. /*
  791. * This bit is OK provided numeq2 does not mess with work_1, ...
  792. * and I think that unless funny tracing or errors occur that should
  793. * be OK.
  794. */
  795. for (i = 1; i<nargs; i++)
  796. { Lisp_Object n1 = r[i];
  797. for (j=0; j<i; j++)
  798. { Lisp_Object n2 = r[j];
  799. CSLbool w = numeq2(n1, n2);
  800. nil = C_nil;
  801. if (exception_pending()) return nil;
  802. if (w) return onevalue(nil);
  803. }
  804. }
  805. return onevalue(lisp_true);
  806. }
  807. Lisp_Object Lneq_2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  808. {
  809. CSLbool w = numeq2(a, b);
  810. errexit();
  811. return onevalue(w ? nil : lisp_true);
  812. }
  813. Lisp_Object Lneq_1(Lisp_Object nil, Lisp_Object a)
  814. {
  815. CSL_IGNORE(nil);
  816. CSL_IGNORE(a);
  817. return onevalue(lisp_true);
  818. }
  819. Lisp_Object MS_CDECL Lgeq_n(Lisp_Object nil, int nargs, ...)
  820. {
  821. va_list a;
  822. int i;
  823. Lisp_Object r;
  824. if (nargs < 2) return onevalue(lisp_true);
  825. if (nargs > ARG_CUT_OFF) return aerror("too many args for >=");
  826. va_start(a, nargs);
  827. push_args(a, nargs);
  828. stackcheck0(nargs);
  829. r = stack[1-nargs];
  830. for (i = 1; i<nargs; i++)
  831. { Lisp_Object s = stack[1+i-nargs];
  832. CSLbool w = lesseq2(s, r);
  833. nil = C_nil;
  834. if (exception_pending()) { popv(nargs); return nil; }
  835. if (!w)
  836. { popv(nargs);
  837. return onevalue(nil);
  838. }
  839. r = s;
  840. }
  841. popv(nargs);
  842. return onevalue(lisp_true);
  843. }
  844. Lisp_Object Lgeq(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  845. {
  846. CSLbool w = lesseq2(b, a);
  847. errexit();
  848. return onevalue(w ? lisp_true : nil);
  849. }
  850. Lisp_Object Lgeq_1(Lisp_Object nil, Lisp_Object a)
  851. {
  852. CSL_IGNORE(nil);
  853. CSL_IGNORE(a);
  854. return onevalue(lisp_true);
  855. }
  856. Lisp_Object MS_CDECL Lleq_n(Lisp_Object nil, int nargs, ...)
  857. {
  858. va_list a;
  859. int i;
  860. Lisp_Object r;
  861. if (nargs < 2) return onevalue(lisp_true);
  862. if (nargs > ARG_CUT_OFF) return aerror("too many args for <=");
  863. va_start(a, nargs);
  864. push_args(a, nargs);
  865. stackcheck0(nargs);
  866. r = stack[1-nargs];
  867. for (i = 1; i<nargs; i++)
  868. { Lisp_Object s = stack[1+i-nargs];
  869. CSLbool fg = lesseq2(r, s);
  870. nil = C_nil;
  871. if (exception_pending()) { popv(nargs);; return nil; }
  872. if (!fg)
  873. { popv(nargs);
  874. return onevalue(nil);
  875. }
  876. r = s;
  877. }
  878. popv(nargs);
  879. return onevalue(lisp_true);
  880. }
  881. Lisp_Object Lleq(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  882. {
  883. CSLbool w = lesseq2(a, b);
  884. errexit();
  885. return onevalue(w ? lisp_true : nil);
  886. }
  887. Lisp_Object Lleq_1(Lisp_Object nil, Lisp_Object a)
  888. {
  889. CSL_IGNORE(nil);
  890. CSL_IGNORE(a);
  891. return onevalue(lisp_true);
  892. }
  893. #else /* COMMON */
  894. Lisp_Object Leqn(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  895. {
  896. CSLbool r;
  897. r = numeq2(a, b);
  898. errexit();
  899. return onevalue(Lispify_predicate(r));
  900. }
  901. Lisp_Object Llessp(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  902. {
  903. CSLbool r;
  904. /*
  905. * I have strongish expectations that fixnum arithmetic is so imporant that
  906. * it is worth lifting the fixnum comparison up here.
  907. */
  908. if (is_fixnum(a) && is_fixnum(b))
  909. return onevalue(Lispify_predicate(a<b));
  910. r = lessp2(a, b);
  911. errexit();
  912. return onevalue(Lispify_predicate(r));
  913. }
  914. Lisp_Object Lgreaterp(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  915. {
  916. CSLbool r;
  917. if (is_fixnum(a) && is_fixnum(b))
  918. return onevalue(Lispify_predicate(a>b));
  919. r = lessp2(b, a);
  920. errexit();
  921. return onevalue(Lispify_predicate(r));
  922. }
  923. Lisp_Object Lgeq(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  924. {
  925. CSLbool r;
  926. if (is_fixnum(a) && is_fixnum(b))
  927. return onevalue(Lispify_predicate(a>=b));
  928. r = lessp2(a, b);
  929. errexit();
  930. return onevalue(Lispify_predicate(!r));
  931. }
  932. Lisp_Object Lleq(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  933. {
  934. CSLbool r;
  935. if (is_fixnum(a) && is_fixnum(b))
  936. return onevalue(Lispify_predicate(a<=b));
  937. r = lessp2(b, a);
  938. errexit();
  939. return onevalue(Lispify_predicate(!r));
  940. }
  941. #endif /* COMMON */
  942. Lisp_Object Lmax2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  943. {
  944. CSLbool w;
  945. CSL_IGNORE(nil);
  946. push2(a, b);
  947. w = lessp2(a, b);
  948. pop2(b, a);
  949. errexit();
  950. if (w) return onevalue(b);
  951. else return onevalue(a);
  952. }
  953. Lisp_Object Lmin2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  954. {
  955. CSLbool w;
  956. CSL_IGNORE(nil);
  957. push2(a, b);
  958. w = lessp2(b, a);
  959. pop2(b, a);
  960. errexit();
  961. if (w) return onevalue(b);
  962. else return onevalue(a);
  963. }
  964. Lisp_Object MS_CDECL Lmax(Lisp_Object nil, int nargs, ...)
  965. {
  966. va_list a;
  967. int i;
  968. Lisp_Object r;
  969. if (nargs < 1) return aerror("max");
  970. if (nargs > ARG_CUT_OFF) return aerror("too many args for max");
  971. va_start(a, nargs);
  972. push_args(a, nargs);
  973. stackcheck0(nargs);
  974. r = stack[1-nargs];
  975. for (i = 1; i<nargs; i++)
  976. { Lisp_Object s = stack[1+i-nargs];
  977. CSLbool fg;
  978. push2(r, s);
  979. fg = lessp2(r, s);
  980. pop2(s, r);
  981. nil = C_nil;
  982. if (exception_pending())
  983. { popv(nargs);
  984. return nil;
  985. }
  986. if (fg) r = s;
  987. }
  988. popv(nargs);
  989. return onevalue(r);
  990. }
  991. Lisp_Object MS_CDECL Lmin(Lisp_Object nil, int nargs, ...)
  992. {
  993. va_list a;
  994. int i;
  995. Lisp_Object r;
  996. if (nargs < 1) return aerror("min");
  997. if (nargs > ARG_CUT_OFF) return aerror("too many args for min");
  998. va_start(a, nargs);
  999. push_args(a, nargs);
  1000. stackcheck0(nargs);
  1001. r = stack[1-nargs];
  1002. for (i = 1; i<nargs; i++)
  1003. { Lisp_Object s = stack[1+i-nargs];
  1004. CSLbool fg;
  1005. push2(r, s);
  1006. fg = lessp2(s, r);
  1007. pop2(s, r);
  1008. nil = C_nil;
  1009. if (exception_pending())
  1010. { popv(nargs);
  1011. return nil;
  1012. }
  1013. if (fg) r = s;
  1014. }
  1015. popv(nargs);
  1016. return onevalue(r);
  1017. }
  1018. Lisp_Object Lrational(Lisp_Object nil, Lisp_Object a)
  1019. {
  1020. a = rational(a);
  1021. errexit();
  1022. return onevalue(a);
  1023. }
  1024. #ifdef COMMON
  1025. static Lisp_Object Lrationalize(Lisp_Object nil, Lisp_Object a)
  1026. {
  1027. a = rationalize(a);
  1028. errexit();
  1029. return onevalue(a);
  1030. }
  1031. #endif
  1032. /*
  1033. * The following random number generator is taken from the Norcroft
  1034. * C library, but is included here so that random sequences will be
  1035. * identical across all implementations of CSL, and because I have bad
  1036. * and pessimistic expectations about the quality of random number
  1037. * generators built into typical C libraries. That is not to say that
  1038. * I ought not to be somewhat cynical about the code I have implemented
  1039. * here! But it is tolerably fast and less dreadful than those old
  1040. * 32-bit linear congruential mistakes.
  1041. */
  1042. static unsigned32 random_number_seed[55];
  1043. static int random_j = 23, random_k = 54;
  1044. static CSLbool randomization_request = NO;
  1045. /*
  1046. * If the user specifies a random number seed of zero I will try to
  1047. * start things in as unpredictable a state as I reasonably can. To
  1048. * achieve this I will update a block of unpredictable data at a
  1049. * number of points during a CSL run, garnering incremental amounts
  1050. * of fairly low grade "randomness" from timing information and the
  1051. * memory addresses that get allocated to CSL. Because it will take
  1052. * a while for such information to build up I arrange that specifying
  1053. * a random seed of zero does not do anything at once (and in particular
  1054. * the implicit call of this nature when CSL starts doe snot do much),
  1055. * but the unpredictable mess I accumulate is inspected the first time
  1056. * any user actually asks for a random value. Since user keyboard input
  1057. * contributes to the clutter it could be that a cautious user will ask the
  1058. * user to type in a long string of gibberish before asking for any
  1059. * random numbers, and the gibberish typed will then in fact form part
  1060. * of the seed that will be used. On Windows I can hook in and make
  1061. * mouse activity etc contribute to the seed too.
  1062. */
  1063. static void randomize()
  1064. {
  1065. int i;
  1066. random_j = 23;
  1067. random_k = 54;
  1068. for (i=20; i<48; i+=4)
  1069. { MD5_Init();
  1070. MD5_Update(unpredictable, sizeof(unpredictable));
  1071. MD5_Final((unsigned char *)&random_number_seed[i]);
  1072. inject_randomness((int)time(NULL));
  1073. }
  1074. /*
  1075. * Note that I do not initialise the whole array of seed values here.
  1076. * Leaving something over can count as part of the unpredictability! But I
  1077. * do try to put in mess through the parts of the seed that will be used
  1078. * first so that any obvious patterns will get clobbered.
  1079. */
  1080. random_number_seed[0] |= 1;
  1081. randomization_request = NO;
  1082. }
  1083. unsigned32 Crand(void)
  1084. {
  1085. /*
  1086. * See Knuth vol 2 section 3.2.2 for a discussion of this random
  1087. * number generator.
  1088. */
  1089. unsigned32 temp;
  1090. if (randomization_request) randomize();
  1091. temp = (random_number_seed[random_k] += random_number_seed[random_j]);
  1092. if (--random_j < 0) random_j = 54, --random_k;
  1093. else if (--random_k < 0) random_k = 54;
  1094. return temp;
  1095. }
  1096. void Csrand(unsigned32 seed, unsigned32 seed2)
  1097. {
  1098. /*
  1099. * This allows you to put 64 bits of seed into the random sequence,
  1100. * but it is very improbable that you have any good source of randomness
  1101. * that good to start with! The input seeds are scrambled using md5
  1102. * and then rather crudely widened to fill the whole array of seed data.
  1103. * If the seed is specified as (0,0) then I will initialise things using
  1104. * information from the time of day and the clock. This is NOT very
  1105. * good, especially since I only use portable C-library ways of reading
  1106. * the time. But it will at least not repeat for any single user and
  1107. * since the clock information is then scrambled via md5 it will APPEAR
  1108. * fairly unpredictable.
  1109. */
  1110. int i;
  1111. random_j = 23;
  1112. random_k = 54;
  1113. i = 0;
  1114. if (seed == 0 && seed2 == 0)
  1115. { randomization_request = YES;
  1116. return;
  1117. }
  1118. randomization_request = NO;
  1119. random_number_seed[0] = seed;
  1120. random_number_seed[1] = 0x12345678;
  1121. random_number_seed[2] = 0xa7086dee;
  1122. random_number_seed[3] = seed2;
  1123. /*
  1124. * Next I will scramble the seed data that I have been given using md5
  1125. * and place the resulting 128 bits of digested stuff in the start of
  1126. * the seed vector.
  1127. */
  1128. MD5_Init();
  1129. MD5_Update((unsigned char *)random_number_seed,
  1130. 4*sizeof(random_number_seed[0]));
  1131. MD5_Final((unsigned char *)&random_number_seed[0]);
  1132. /*
  1133. * The remainder of the vector gets filled using a simple linear
  1134. * congruential scheme.
  1135. */
  1136. i = 4;
  1137. seed = random_number_seed[0];
  1138. while (i<55)
  1139. { seed = 69069*seed + 1725307361; /* computed modulo 2^32 */
  1140. random_number_seed[i++] = seed;
  1141. }
  1142. /*
  1143. * I would like to make the least significant bits a little less
  1144. * regular even to start with, so I xor in from one of the words that
  1145. * md5 gave me.
  1146. */
  1147. seed = random_number_seed[1];
  1148. i = 55-30;
  1149. while (i<55)
  1150. { random_number_seed[i++] ^= seed & 1;
  1151. seed = seed >> 1;
  1152. }
  1153. /*
  1154. * If all the least significant bits were zero to start with they would
  1155. * always stay that way, so I force one of them to be 1.
  1156. */
  1157. random_number_seed[21] |= 1;
  1158. }
  1159. #ifdef COMMON
  1160. Lisp_Object Lrandom_2(Lisp_Object nil, Lisp_Object a, Lisp_Object bb)
  1161. {
  1162. Lisp_Object b;
  1163. /*
  1164. * Common Lisp expects an optional second arg to be used for the random
  1165. * state - at present I do not support that, but it will not be too hard
  1166. * when I get around to it...
  1167. */
  1168. b = bb;
  1169. CSL_IGNORE(nil);
  1170. if (is_fixnum(a))
  1171. { int32 v = int_of_fixnum(a), p, q;
  1172. if (v <= 0) return aerror1("random", a);
  1173. /* (random 1) always returns zero - a rather silly case! */
  1174. else if (v == 1) return onevalue(fixnum_of_int(0));
  1175. /*
  1176. * I generate a value that is an exact multiple of my range (v) and
  1177. * pick random bitpatterns until I find one less than that. On average
  1178. * I will have only VERY slightly less than one draw needed, and doing things
  1179. * this way ought to ensure that my pseudo random numbers are uniformly
  1180. * distributed provided that the underlying generator is well behaved.
  1181. */
  1182. p = v*(0x7fffffff/v);
  1183. do q = ((unsigned32)Crand()) >> 1; while (q > p);
  1184. return onevalue(fixnum_of_int(q % v));
  1185. }
  1186. if (is_numbers(a))
  1187. { int32 len, len1, msd;
  1188. unsigned32 w, w1;
  1189. Lisp_Object r;
  1190. if (!is_bignum(a)) return aerror1("random", a);
  1191. len = bignum_length(a);
  1192. push(a);
  1193. r = getvector(TAG_NUMBERS, TYPE_BIGNUM, len);
  1194. pop(a);
  1195. errexit();
  1196. len1 = (len>>2)-2;
  1197. restart:
  1198. len = len1;
  1199. msd = bignum_digits(a)[len];
  1200. if (msd < 0) return aerror("negative arg for random"); /* -ve arg */
  1201. if (msd == 0)
  1202. { bignum_digits(r)[len] = 0;
  1203. len--;
  1204. msd = bignum_digits(a)[len];
  1205. }
  1206. for (;;)
  1207. { w = (0xffffffffU/((unsigned32)msd+1U))*((unsigned32)msd+1U);
  1208. do w1 = (unsigned32)Crand(); while (w1 >= w);
  1209. w1 = w1%((unsigned32)msd+1U);
  1210. bignum_digits(r)[len] = w1;
  1211. if ((int32)w1 != msd) break;
  1212. /*
  1213. * The loop to restart on the next line is when the random value I
  1214. * have built up word by word ends up being equal to the input number - I
  1215. * will discard it and start again in that case.
  1216. */
  1217. if (len == 0) goto restart;
  1218. len--;
  1219. msd = bignum_digits(a)[len];
  1220. }
  1221. /*
  1222. * having got some leading digits properly set up I can fill in the rest
  1223. * as totally independent bit-patterns.
  1224. */
  1225. for (len--;len>=0; len--)
  1226. bignum_digits(r)[len] = ((unsigned32)Crand())>>1;
  1227. return onevalue(shrink_bignum(r, len1));
  1228. }
  1229. if (is_bfloat(a))
  1230. { Header h = flthdr(a);
  1231. double d = float_of_number(a), v;
  1232. /*
  1233. * The calculation here turns 62 bits of integer data into a floating
  1234. * point number in the range 0.0 (inclusive) to 1.0 (exclusive). Well,
  1235. * to be more precise, rounding the value to the machine's floating point
  1236. * format may round it up to be exactly 1.0, so I discard and cases where
  1237. * that happens (once in several blue moons...). If I wrote code that
  1238. * knew exactly how many bits my floating point format had I could avoid
  1239. * the need for that extra test, but it does not seem very painful to me
  1240. * and I prefer the more portable code.
  1241. */
  1242. do
  1243. { v = ((double)(int32)(Crand() & 0x7fffffff)) / TWO_31;
  1244. v += (double)(int32)(Crand() & 0x7fffffff);
  1245. v /= TWO_31;
  1246. v *= d;
  1247. } while (v == d);
  1248. a = make_boxfloat(v, type_of_header(h));
  1249. errexit();
  1250. return onevalue(a);
  1251. }
  1252. if (is_sfloat(a))
  1253. { Float_union d;
  1254. float v;
  1255. d.i = a - TAG_SFLOAT;
  1256. /*
  1257. * similar idea to boxfloat case, but only 31 bits randomness used.
  1258. * SOFTWARE_FLOATING_POINT conversion needed here, maybe
  1259. */
  1260. do
  1261. { v = (float)(int32)(Crand() & 0x7fffffff)/(float)TWO_31;
  1262. v = v*d.f;
  1263. } while (v == d.f);
  1264. d.f = v;
  1265. return onevalue((d.i & ~(int32)0xf) + TAG_SFLOAT);
  1266. }
  1267. return aerror1("random", a);
  1268. }
  1269. #endif
  1270. Lisp_Object Lrandom(Lisp_Object nil, Lisp_Object a)
  1271. {
  1272. CSL_IGNORE(nil);
  1273. if (is_fixnum(a))
  1274. { int32 v = int_of_fixnum(a), p, q;
  1275. if (v <= 0) return aerror1("random", a);
  1276. /* (random 1) always returns zero - a rather silly case! */
  1277. else if (v == 1) return onevalue(fixnum_of_int(0));
  1278. /*
  1279. * I generate a value that is an exact multiple of my range (v) and
  1280. * pick random bitpatterns until I find one less than that. On average
  1281. * I will have only VERY slightly less than one draw needed, and doing things
  1282. * this way ought to ensure that my pseudo random numbers are uniformly
  1283. * distributed provided that the underlying generator is well behaved.
  1284. */
  1285. p = v*(0x7fffffff/v);
  1286. do q = ((unsigned32)Crand()) >> 1; while (q > p);
  1287. return onevalue(fixnum_of_int(q % v));
  1288. }
  1289. if (is_numbers(a))
  1290. { int32 len, len1, msd;
  1291. unsigned32 w, w1;
  1292. Lisp_Object r;
  1293. if (!is_bignum(a)) return aerror1("random", a);
  1294. len = bignum_length(a);
  1295. push(a);
  1296. r = getvector(TAG_NUMBERS, TYPE_BIGNUM, len);
  1297. pop(a);
  1298. errexit();
  1299. len1 = (len>>2)-2;
  1300. restart:
  1301. len = len1;
  1302. msd = bignum_digits(a)[len];
  1303. if (msd < 0) return aerror("negative arg for random"); /* -ve arg */
  1304. if (msd == 0)
  1305. { bignum_digits(r)[len] = 0;
  1306. len--;
  1307. msd = bignum_digits(a)[len];
  1308. }
  1309. for (;;)
  1310. { w = (0xffffffffU/((unsigned32)msd+1U))*((unsigned32)msd+1U);
  1311. do w1 = (unsigned32)Crand(); while (w1 >= w);
  1312. w1 = w1%((unsigned32)msd+1U);
  1313. bignum_digits(r)[len] = w1;
  1314. if ((int32)w1 != msd) break;
  1315. /*
  1316. * The loop to restart on the next line is when the random value I
  1317. * have built up word by word ends up being equal to the input number - I
  1318. * will discard it and start again in that case.
  1319. */
  1320. if (len == 0) goto restart;
  1321. len--;
  1322. msd = bignum_digits(a)[len];
  1323. }
  1324. /*
  1325. * having got some leading digits properly set up I can fill in the rest
  1326. * as totally independent bit-patterns.
  1327. */
  1328. for (len--;len>=0; len--)
  1329. bignum_digits(r)[len] = ((unsigned32)Crand())>>1;
  1330. return onevalue(shrink_bignum(r, len1));
  1331. }
  1332. if (is_bfloat(a))
  1333. { Header h = flthdr(a);
  1334. double d = float_of_number(a), v;
  1335. /*
  1336. * The calculation here turns 62 bits of integer data into a floating
  1337. * point number in the range 0.0 (inclusive) to 1.0 (exclusive). Well,
  1338. * to be more precise, rounding the value to the machine's floating point
  1339. * format may round it up to be exactly 1.0, so I discard and cases where
  1340. * that happens (once in several blue moons...). If I wrote code that
  1341. * knew exactly how many bits my floating point format had I could avoid
  1342. * the need for that extra test, but it does not seem very painful to me
  1343. * and I prefer the more portable code.
  1344. */
  1345. do
  1346. { v = ((double)(int32)(Crand() & 0x7fffffff)) / TWO_31;
  1347. v += (double)(int32)(Crand() & 0x7fffffff);
  1348. v /= TWO_31;
  1349. v *= d;
  1350. } while (v == d);
  1351. a = make_boxfloat(v, type_of_header(h));
  1352. errexit();
  1353. return onevalue(a);
  1354. }
  1355. #ifdef COMMON
  1356. if (is_sfloat(a))
  1357. { Float_union d;
  1358. float v;
  1359. d.i = a - TAG_SFLOAT;
  1360. /*
  1361. * similar idea to boxfloat case, but only 31 bits randomness used.
  1362. * SOFTWARE_FLOATING_POINT conversion needed here, maybe
  1363. */
  1364. do
  1365. { v = (float)(int32)(Crand() & 0x7fffffff)/(float)TWO_31;
  1366. v = v*d.f;
  1367. } while (v == d.f);
  1368. d.f = v;
  1369. return onevalue((d.i & ~(int32)0xf) + TAG_SFLOAT);
  1370. }
  1371. #endif
  1372. return aerror1("random", a);
  1373. }
  1374. Lisp_Object MS_CDECL Lnext_random(Lisp_Object nil, int nargs, ...)
  1375. /*
  1376. * Returns a random positive fixnum. 27 bits in this Lisp!
  1377. */
  1378. {
  1379. int32 r;
  1380. argcheck(nargs, 0, "next-random");
  1381. CSL_IGNORE(nil);
  1382. r = Crand();
  1383. return onevalue((Lisp_Object)((r & 0x7ffffff0) + TAG_FIXNUM));
  1384. }
  1385. Lisp_Object Lmake_random_state(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  1386. {
  1387. /*
  1388. * Nasty temporary hack here to allow me to set the seed for the
  1389. * random number generator in Standard Lisp mode. I need to re-think
  1390. * this soon before it feels frozen in! Oops - too late!!!
  1391. */
  1392. CSL_IGNORE(b);
  1393. if (!is_fixnum(a)) return aerror1("make-random-state", a);
  1394. Csrand(int_of_fixnum(a),
  1395. is_fixnum(b) ? int_of_fixnum(b) : 0);
  1396. return onevalue(nil);
  1397. }
  1398. Lisp_Object Lmake_random_state1(Lisp_Object nil, Lisp_Object a)
  1399. {
  1400. if (!is_fixnum(a)) return aerror1("make-random-state", a);
  1401. Csrand(int_of_fixnum(a), 0);
  1402. return onevalue(nil);
  1403. }
  1404. /*
  1405. * The function md5() can be given a number or a string as an argument,
  1406. * and it uses the md5 message digest algorithm to reduce it to a
  1407. * numeric value in the range 0 to 2^128.
  1408. * Well actually I will also allow an arbitrary expression, which I
  1409. * will treat as if it has to be printed...
  1410. */
  1411. Lisp_Object Lmd5(Lisp_Object env, Lisp_Object a)
  1412. {
  1413. Lisp_Object nil = C_nil;
  1414. Lisp_Object r;
  1415. unsigned char md[16];
  1416. unsigned32 v0, v1, v2, v3, v4;
  1417. int32 len, i;
  1418. if (is_fixnum(a))
  1419. { sprintf((char *)md, "%.8lx", (unsigned long)a);
  1420. MD5_Init();
  1421. MD5_Update(md, 8);
  1422. }
  1423. else if (is_numbers(a) && is_bignum_header(numhdr(a)))
  1424. { len = length_of_header(numhdr(a));
  1425. MD5_Init();
  1426. for (i=4; i<len; i+=4)
  1427. { sprintf((char *)md, "%.8lx", (unsigned long)bignum_digits(a)[(i-4)/4]);
  1428. MD5_Update(md, 8);
  1429. }
  1430. }
  1431. else if (is_vector(a) && type_of_header(vechdr(a)) == TYPE_STRING)
  1432. { len = length_of_header(vechdr(a));
  1433. MD5_Init();
  1434. MD5_Update((unsigned char *)(a - TAG_VECTOR + 4), len-4);
  1435. }
  1436. else checksum(a);
  1437. MD5_Final(md);
  1438. v0 = md[0] + (md[1]<<8) + (md[2]<<16) + (md[3]<<24);
  1439. v1 = md[4] + (md[5]<<8) + (md[6]<<16) + (md[7]<<24);
  1440. v2 = md[8] + (md[9]<<8) + (md[10]<<16) + (md[11]<<24);
  1441. v3 = md[12] + (md[13]<<8) + (md[14]<<16) + (md[15]<<24);
  1442. v4 = v3 >> 28;
  1443. v3 = ((v3 << 3) | (v2 >> 29)) & 0x7fffffff;
  1444. v2 = ((v2 << 2) | (v1 >> 30)) & 0x7fffffff;
  1445. v1 = ((v1 << 1) | (v0 >> 31)) & 0x7fffffff;
  1446. v0 &= 0x7fffffff;
  1447. /*
  1448. * Note the funny tests. This is because in my representation the
  1449. * top word of a bignum is a 2s complement signed value and to keep clear
  1450. * of overflow that means I use an extra digit slightly before one might
  1451. * imagine it is necessary!
  1452. */
  1453. if (v4 != 0 || (v3 & 0x40000000) != 0) len = 24;
  1454. else if (v3 != 0 || (v2 & 0x40000000) != 0) len = 20;
  1455. else if (v2 != 0 || (v1 & 0x40000000) != 0) len = 16;
  1456. else if (v1 != 0 || (v0 & 0x40000000) != 0) len = 12;
  1457. else if ((v0 & fix_mask) != 0) len = 8;
  1458. else return onevalue(fixnum_of_int(v0));
  1459. r = getvector(TAG_NUMBERS, TYPE_BIGNUM, len);
  1460. errexit();
  1461. switch (len)
  1462. {
  1463. case 24:
  1464. case 20: bignum_digits(r)[4] = v4; /* zeros out padding word as necessary */
  1465. bignum_digits(r)[3] = v3;
  1466. case 16:
  1467. case 12: bignum_digits(r)[2] = v2;
  1468. bignum_digits(r)[1] = v1;
  1469. case 8: bignum_digits(r)[0] = v0;
  1470. break;
  1471. }
  1472. /* validate_number("MD5", r, r, r); */
  1473. return onevalue(r);
  1474. }
  1475. /*
  1476. * md60 is a function that uses MD5 but then returns just about 60 bits
  1477. * of number not 128. It is for use when the full 128 bits of checksum
  1478. * would be clumsy overkill.
  1479. */
  1480. Lisp_Object Lmd60(Lisp_Object env, Lisp_Object a)
  1481. {
  1482. Lisp_Object nil = C_nil;
  1483. Lisp_Object r;
  1484. unsigned char md[16];
  1485. unsigned32 v0, v1;
  1486. int32 len, i;
  1487. if (is_fixnum(a))
  1488. { sprintf((char *)md, "%.8lx", (unsigned long)a);
  1489. MD5_Init();
  1490. MD5_Update(md, 8);
  1491. }
  1492. else if (is_numbers(a) && is_bignum_header(numhdr(a)))
  1493. { len = length_of_header(numhdr(a));
  1494. MD5_Init();
  1495. for (i=4; i<len; i+=4)
  1496. { sprintf((char *)md, "%.8lx", (unsigned long)bignum_digits(a)[(i-4)/4]);
  1497. MD5_Update(md, 8);
  1498. }
  1499. }
  1500. else if (is_vector(a) && type_of_header(vechdr(a)) == TYPE_STRING)
  1501. { len = length_of_header(vechdr(a));
  1502. MD5_Init();
  1503. MD5_Update((unsigned char *)(a - TAG_VECTOR + 4), len-4);
  1504. }
  1505. else checksum(a);
  1506. MD5_Final(md);
  1507. v0 = md[0] + (md[1]<<8) + (md[2]<<16) + (md[3]<<24);
  1508. v1 = md[4] + (md[5]<<8) + (md[6]<<16) + (md[7]<<24);
  1509. v1 = ((v1 << 1) | (v0 >> 31)) & 0x3fffffff;
  1510. v0 &= 0x7fffffff;
  1511. if (v1 != 0 || (v0 & 0x40000000) != 0) len = 12;
  1512. else if ((v0 & fix_mask) != 0) len = 8;
  1513. else return onevalue(fixnum_of_int(v0));
  1514. r = getvector(TAG_NUMBERS, TYPE_BIGNUM, len);
  1515. errexit();
  1516. switch (len)
  1517. {
  1518. case 12: bignum_digits(r)[2] = 0;
  1519. bignum_digits(r)[1] = v1;
  1520. case 8: bignum_digits(r)[0] = v0;
  1521. break;
  1522. }
  1523. /* validate_number("MD60", r, r, r); */
  1524. return onevalue(r);
  1525. }
  1526. static Lisp_Object Llogand2(Lisp_Object env, Lisp_Object a1, Lisp_Object a2)
  1527. {
  1528. return Lboolfn(env, 2, a1, a2);
  1529. }
  1530. static Lisp_Object Llogeqv2(Lisp_Object env, Lisp_Object a1, Lisp_Object a2)
  1531. {
  1532. return Lboolfn(env, 2, a1, a2);
  1533. }
  1534. static Lisp_Object Llogxor2(Lisp_Object env, Lisp_Object a1, Lisp_Object a2)
  1535. {
  1536. return Lboolfn(env, 2, a1, a2);
  1537. }
  1538. static Lisp_Object Llogor2(Lisp_Object env, Lisp_Object a1, Lisp_Object a2)
  1539. {
  1540. return Lboolfn(env, 2, a1, a2);
  1541. }
  1542. static Lisp_Object MS_CDECL Ldemo_mode(Lisp_Object nil, int nargs, ...)
  1543. {
  1544. argcheck(nargs, 0, "demo-mode");
  1545. #ifdef DEMO_BUILD
  1546. if (qfn1(compiler_symbol) == undefined1)
  1547. { Csrand(demo_key1, demo_key2);
  1548. return onevalue(lisp_true);
  1549. }
  1550. #endif
  1551. return onevalue(nil);
  1552. }
  1553. setup_type const arith06_setup[] =
  1554. {
  1555. {"ash", too_few_2, Lash, wrong_no_2},
  1556. {"ash1", too_few_2, Lash1, wrong_no_2},
  1557. {"divide", too_few_2, Ldivide, wrong_no_2},
  1558. {"evenp", Levenp, too_many_1, wrong_no_1},
  1559. {"inorm", too_few_2, Linorm, wrong_no_2},
  1560. {"logand", Lidentity, Llogand2, Lboolfn},
  1561. {"logeqv", Lidentity, Llogeqv2, Lboolfn},
  1562. {"lognot", Llognot, too_many_1, wrong_no_1},
  1563. {"logxor", Lidentity, Llogxor2, Lboolfn},
  1564. {"lsd", Llsd, too_many_1, wrong_no_1},
  1565. {"make-random-state", Lmake_random_state1, Lmake_random_state, wrong_no_2},
  1566. {"max", Lidentity, Lmax2, Lmax},
  1567. {"max2", too_few_2, Lmax2, wrong_no_2},
  1568. {"min", Lidentity, Lmin2, Lmin},
  1569. {"min2", too_few_2, Lmin2, wrong_no_2},
  1570. {"minus", Lminus, too_many_1, wrong_no_1},
  1571. {"minusp", Lminusp, too_many_1, wrong_no_1},
  1572. {"mod", too_few_2, Lmod, wrong_no_2},
  1573. {"msd", Lmsd, too_many_1, wrong_no_1},
  1574. {"oddp", Loddp, too_many_1, wrong_no_1},
  1575. {"onep", Lonep, too_many_1, wrong_no_1},
  1576. {"plus2", too_few_2, Lplus2, wrong_no_2},
  1577. {"plusp", Lplusp, too_many_1, wrong_no_1},
  1578. {"rational", Lrational, too_many_1, wrong_no_1},
  1579. {"times2", too_few_2, Ltimes2, wrong_no_2},
  1580. {"zerop", Lzerop, too_many_1, wrong_no_1},
  1581. {"md5", Lmd5, too_many_1, wrong_no_1},
  1582. {"md60", Lmd60, too_many_1, wrong_no_1},
  1583. {"demo-mode", wrong_no_0a, wrong_no_0b, Ldemo_mode},
  1584. #ifdef COMMON
  1585. {"*", Lidentity, Ltimes2, Ltimes},
  1586. {"+", Lidentity, Lplus2, Lplus},
  1587. {"-", Lminus, Ldifference2, Ldifference},
  1588. {"/", Lquotient_1, Lquotient, Lquotient_n},
  1589. {"/=", Lneq_1, Lneq_2, Lneqn},
  1590. {"1+", Ladd1, too_many_1, wrong_no_1},
  1591. {"1-", Lsub1, too_many_1, wrong_no_1},
  1592. {"<", Llessp_1, Llessp, Llessp_n},
  1593. {"<=", Lleq_1, Lleq, Lleq_n},
  1594. {"=", Leqn_1, Leqn, Leqn_n},
  1595. {">", Lgreaterp_1, Lgreaterp, Lgreaterp_n},
  1596. {">=", Lgeq_1, Lgeq, Lgeq_n},
  1597. {"float", Lfloat, Lfloat_2, wrong_no_1},
  1598. {"logior", Lidentity, Llogor2, Lboolfn},
  1599. {"random", Lrandom, Lrandom_2, wrong_no_1},
  1600. {"rationalize", Lrationalize, too_many_1, wrong_no_1},
  1601. {"rem", too_few_2, Lrem, wrong_no_2},
  1602. /*
  1603. * I also provide the old style names to make porting code easier for me
  1604. */
  1605. {"times", Lidentity, Ltimes2, Ltimes},
  1606. {"plus", Lidentity, Lplus2, Lplus},
  1607. {"times2", too_few_2, Ltimes2, wrong_no_2},
  1608. {"plus2", too_few_2, Lplus2, wrong_no_2},
  1609. {"minus", Lminus, too_many_1, wrong_no_1},
  1610. {"difference", too_few_2, Ldifference2, Ldifference},
  1611. /* I leave QUOTIENT as the integer-truncating form, while "/" gives ratios */
  1612. {"quotient", too_few_2, LSLquotient, wrong_no_2},
  1613. {"remainder", too_few_2, Lrem, wrong_no_2},
  1614. {"add1", Ladd1, too_many_1, wrong_no_1},
  1615. {"sub1", Lsub1, too_many_1, wrong_no_1},
  1616. {"lessp", Llessp_1, Llessp, Llessp_n},
  1617. {"leq", Lleq_1, Lleq, Lleq_n},
  1618. {"eqn", Leqn_1, Leqn, Leqn_n},
  1619. {"greaterp", Lgreaterp_1, Lgreaterp, Lgreaterp_n},
  1620. {"geq", Lgeq_1, Lgeq, Lgeq_n},
  1621. {"next-random-number", wrong_no_0a, wrong_no_0b, Lnext_random},
  1622. #else
  1623. {"add1", Ladd1, too_many_1, wrong_no_1},
  1624. {"difference", too_few_2, Ldifference2, wrong_no_2},
  1625. {"eqn", too_few_2, Leqn, wrong_no_2},
  1626. {"float", Lfloat, too_many_1, wrong_no_1},
  1627. {"geq", too_few_2, Lgeq, wrong_no_2},
  1628. {"greaterp", too_few_2, Lgreaterp, wrong_no_2},
  1629. {"leq", too_few_2, Lleq, wrong_no_2},
  1630. {"lessp", too_few_2, Llessp, wrong_no_2},
  1631. {"logor", Lidentity, Llogor2, Lboolfn},
  1632. {"quotient", too_few_2, Lquotient, wrong_no_2},
  1633. /*
  1634. * I used to call these just random and next-random-number, but REDUCE
  1635. * wants its own versions of those (for cross-Lisp consistency) so I use
  1636. * alternative names here.
  1637. */
  1638. {"random-number", Lrandom, too_many_1, wrong_no_1},
  1639. {"random-fixnum", wrong_no_0a, wrong_no_0b, Lnext_random},
  1640. {"remainder", too_few_2, Lrem, wrong_no_2},
  1641. {"sub1", Lsub1, too_many_1, wrong_no_1},
  1642. #endif
  1643. {NULL, 0, 0, 0}
  1644. };
  1645. /* end of arith06.c */