arith06.c 56 KB

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