PageRenderTime 65ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/s9core.c

http://github.com/barak/scheme9
C | 3560 lines | 3076 code | 334 blank | 150 comment | 905 complexity | 237d5035699b8407ca3c11685bb16c3f MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * S9core Toolkit, Mk IVc
  3. * By Nils M Holm, 2007-2018
  4. * In the public domain
  5. *
  6. * Under jurisdictions without a public domain, the CC0 applies:
  7. * https://creativecommons.org/publicdomain/zero/1.0/
  8. */
  9. #include "s9core.h"
  10. #define S9_S9CORE
  11. #include "s9import.h"
  12. #include "s9ext.h"
  13. /*
  14. * Global state
  15. */
  16. static int Cons_segment_size,
  17. Vec_segment_size;
  18. static int Cons_pool_size,
  19. Vec_pool_size;
  20. static int Verbose_GC = 0;
  21. s9_cell *Car,
  22. *Cdr;
  23. char *Tag;
  24. s9_cell *Vectors;
  25. s9_cell Nullvec;
  26. s9_cell Nullstr;
  27. s9_cell Blank;
  28. cell Stack;
  29. static cell Protect;
  30. static int Protp;
  31. static cell Free_list;
  32. static cell Free_vecs;
  33. S9_PRIM *Primitives;
  34. static int Last_prim,
  35. Max_prims;
  36. static cell Tmp_car,
  37. Tmp_cdr,
  38. Tmp;
  39. static cell Symbols;
  40. static cell Symhash;
  41. static int Printer_count,
  42. Printer_limit;
  43. static int IO_error;
  44. FILE *Ports[S9_MAX_PORTS];
  45. static char Port_flags[S9_MAX_PORTS];
  46. int Input_port,
  47. Output_port,
  48. Error_port;
  49. static volatile int Abort_flag;
  50. static char *Str_outport;
  51. static int Str_outport_len;
  52. static char *Str_inport;
  53. static char Rejected[2];
  54. static long Node_limit,
  55. Vector_limit;
  56. static char *Exponent_chars;
  57. static cell **Image_vars;
  58. static void (*Mem_error_handler)(int src);
  59. /* Predefined bignum literals */
  60. cell Zero,
  61. One,
  62. Two,
  63. Ten;
  64. /* Smallest value by which two real numbers can differ:
  65. * 10 ^ -(S9_MANTISSA_SIZE+1)
  66. */
  67. cell Epsilon;
  68. /* Internal GC roots */
  69. static cell *GC_int_roots[] = {
  70. &Stack, &Symbols, &Symhash, &Tmp, &Tmp_car,
  71. &Tmp_cdr, &Zero, &One, &Two, &Ten, &Epsilon,
  72. &Nullvec, &Nullstr, &Blank, &Protect, NULL };
  73. /* External GC roots */
  74. static cell **GC_ext_roots = NULL;
  75. /* GC stack */
  76. cell *S9_gc_stack;
  77. int *S9_gc_stkptr;
  78. /*
  79. * Internal vector representation
  80. */
  81. #define RAW_VECTOR_LINK 0
  82. #define RAW_VECTOR_INDEX 1
  83. #define RAW_VECTOR_SIZE 2
  84. #define RAW_VECTOR_DATA 3
  85. /*
  86. * Internal node protection
  87. */
  88. #ifdef S9_BITS_PER_WORD_64
  89. #define PROT_STACK_LEN 400
  90. #else
  91. #define PROT_STACK_LEN 200
  92. #endif
  93. static void prot(cell x) {
  94. if (Protp >= PROT_STACK_LEN-1)
  95. s9_fatal("internal prot() stack overflow");
  96. vector(Protect)[++Protp] = x;
  97. }
  98. static cell unprot(int n) {
  99. cell x;
  100. if (Protp - n < -1)
  101. s9_fatal("internal prot() stack underflow");
  102. x = vector(Protect)[Protp-n+1];
  103. while (n) {
  104. vector(Protect)[Protp--] = UNDEFINED;
  105. n--;
  106. }
  107. return x;
  108. }
  109. #define pref(n) (vector(Protect)[Protp-(n)])
  110. /*
  111. * Counting
  112. */
  113. static int Run_stats, Cons_stats;
  114. static s9_counter Conses,
  115. Nodes,
  116. Vecspace,
  117. Collections;
  118. void s9_run_stats(int x) {
  119. Run_stats = x;
  120. if (Run_stats) {
  121. s9_reset_counter(&Nodes);
  122. s9_reset_counter(&Conses);
  123. s9_reset_counter(&Vecspace);
  124. s9_reset_counter(&Collections);
  125. }
  126. }
  127. void s9_cons_stats(int x) {
  128. Cons_stats = x;
  129. }
  130. void s9_reset_counter(s9_counter *c) {
  131. c->n = 0;
  132. c->n1k = 0;
  133. c->n1m = 0;
  134. c->n1g = 0;
  135. c->n1t = 0;
  136. }
  137. void s9_count(s9_counter *c) {
  138. c->n++;
  139. if (c->n >= 1000) {
  140. c->n -= 1000;
  141. c->n1k++;
  142. if (c->n1k >= 1000) {
  143. c->n1k -= 1000;
  144. c->n1m++;
  145. if (c->n1m >= 1000) {
  146. c->n1m -= 1000;
  147. c->n1g++;
  148. if (c->n1g >= 1000) {
  149. c->n1g -= 1000;
  150. c->n1t++;
  151. }
  152. }
  153. }
  154. }
  155. }
  156. void s9_countn(s9_counter *c, int n) {
  157. c->n += n;
  158. if (c->n >= 1000) {
  159. c->n1k += c->n / 1000;
  160. c->n = c->n % 1000;
  161. if (c->n1k >= 1000) {
  162. c->n1m += c->n1k / 1000;
  163. c->n1k = c->n1k % 1000;
  164. if (c->n1m >= 1000) {
  165. c->n1g += c->n1m / 1000;
  166. c->n1m = c->n1m % 1000;
  167. if (c->n1g >= 1000) {
  168. c->n1t += c->n1g / 1000;
  169. c->n1g = c->n1g % 1000;
  170. }
  171. }
  172. }
  173. }
  174. }
  175. cell s9_read_counter(s9_counter *c) {
  176. cell n, m;
  177. n = s9_make_integer(c->n);
  178. n = cons(n, NIL);
  179. prot(n);
  180. m = s9_make_integer(c->n1k);
  181. n = cons(m, n);
  182. pref(0) = n;
  183. m = s9_make_integer(c->n1m);
  184. n = cons(m, n);
  185. pref(0) = n;
  186. m = s9_make_integer(c->n1g);
  187. n = cons(m, n);
  188. pref(0) = n;
  189. m = s9_make_integer(c->n1t);
  190. n = cons(m, n);
  191. unprot(1);
  192. return n;
  193. }
  194. void s9_get_counters(s9_counter **nc, s9_counter **cc, s9_counter **vc,
  195. s9_counter **gc) {
  196. *nc = &Nodes;
  197. *cc = &Conses;
  198. *vc = &Vecspace;
  199. *gc = &Collections;
  200. }
  201. /*
  202. * Raw I/O
  203. */
  204. int s9_inport_open_p(void) {
  205. return Ports[Input_port] != NULL;
  206. }
  207. int s9_outport_open_p(void) {
  208. return Ports[Output_port] != NULL;
  209. }
  210. int s9_readc(void) {
  211. int c, i;
  212. if (Str_inport != NULL) {
  213. for (i=1; i>=0; i--) {
  214. if (Rejected[i] > -1) {
  215. c = Rejected[i];
  216. Rejected[i] = -1;
  217. return c;
  218. }
  219. }
  220. if (0 == *Str_inport) {
  221. return EOF;
  222. }
  223. else {
  224. return *Str_inport++;
  225. }
  226. }
  227. else {
  228. if (!s9_inport_open_p())
  229. s9_fatal("s9_readc(): input port is not open");
  230. return getc(Ports[Input_port]);
  231. }
  232. }
  233. void s9_rejectc(int c) {
  234. if (Str_inport != NULL) {
  235. if (Rejected[0] == -1)
  236. Rejected[0] = c;
  237. else
  238. Rejected[1] = c;
  239. }
  240. else {
  241. ungetc(c, Ports[Input_port]);
  242. }
  243. }
  244. void s9_writec(int c) {
  245. if (!s9_outport_open_p())
  246. s9_fatal("s9_writec(): output port is not open");
  247. (void) putc(c, Ports[Output_port]);
  248. }
  249. char *s9_open_input_string(char *s) {
  250. char *os;
  251. os = Str_inport;
  252. Str_inport = s;
  253. Rejected[0] = Rejected[1] = -1;
  254. return os;
  255. }
  256. void s9_close_input_string(void) {
  257. Str_inport = NULL;
  258. }
  259. void s9_flush(void) {
  260. if (fflush(Ports[Output_port]))
  261. IO_error = 1;
  262. }
  263. void s9_set_printer_limit(int k) {
  264. Printer_limit = k;
  265. Printer_count = 0;
  266. }
  267. int s9_printer_limit(void) {
  268. return Printer_limit && Printer_count >= Printer_limit;
  269. }
  270. void s9_blockwrite(char *s, int k) {
  271. if (Str_outport) {
  272. if (k >= Str_outport_len) {
  273. k = Str_outport_len;
  274. IO_error = 1;
  275. }
  276. memcpy(Str_outport, s, k);
  277. Str_outport += k;
  278. Str_outport_len -= k;
  279. *Str_outport = 0;
  280. return;
  281. }
  282. if (!s9_outport_open_p())
  283. s9_fatal("s9_blockwrite(): output port is not open");
  284. if (Printer_limit && Printer_count > Printer_limit) {
  285. if (Printer_limit > 0)
  286. fwrite("...", 1, 3, Ports[Output_port]);
  287. Printer_limit = -1;
  288. return;
  289. }
  290. if (fwrite(s, 1, k, Ports[Output_port]) != k)
  291. IO_error = 1;
  292. if (Output_port == 1 && s[k-1] == '\n')
  293. s9_flush();
  294. Printer_count += k;
  295. }
  296. int s9_blockread(char *s, int k) {
  297. int n;
  298. if (!s9_inport_open_p())
  299. s9_fatal("s9_blockread(): input port is not open");
  300. n = fread(s, 1, k, Ports[Input_port]);
  301. if (n < 0) IO_error = 1;
  302. return n;
  303. }
  304. void s9_prints(char *s) {
  305. s9_blockwrite(s, strlen(s));
  306. }
  307. int s9_io_status(void) {
  308. return IO_error? -1: 0;
  309. }
  310. void s9_io_reset(void) {
  311. IO_error = 0;
  312. }
  313. /*
  314. * Error Handling
  315. */
  316. void s9_fatal(char *msg) {
  317. fprintf(stderr, "S9core: fatal error: ");
  318. fprintf(stderr, "%s\n", msg);
  319. bye(1);
  320. }
  321. void s9_abort(void) {
  322. Abort_flag = 1;
  323. }
  324. void s9_reset(void) {
  325. Abort_flag = 0;
  326. }
  327. /*
  328. * Memory Management
  329. */
  330. void s9_set_node_limit(int n) {
  331. Node_limit = n * 1024L;
  332. }
  333. void s9_set_vector_limit(int n) {
  334. Vector_limit = n * 1024L;
  335. }
  336. void s9_gc_verbosity(int n) {
  337. Verbose_GC = n;
  338. }
  339. void s9_mem_error_handler(void (*h)(int src)) {
  340. Mem_error_handler = h;
  341. }
  342. static void new_cons_segment(void) {
  343. Car = realloc(Car, sizeof(cell)*(Cons_pool_size+Cons_segment_size));
  344. Cdr = realloc(Cdr, sizeof(cell)*(Cons_pool_size+Cons_segment_size));
  345. Tag = realloc(Tag, Cons_pool_size + Cons_segment_size);
  346. if (Car == NULL || Cdr == NULL || Tag == NULL)
  347. s9_fatal("new_cons_segment: out of physical memory");
  348. memset(&car(Cons_pool_size), 0, Cons_segment_size * sizeof(cell));
  349. memset(&cdr(Cons_pool_size), 0, Cons_segment_size * sizeof(cell));
  350. memset(&Tag[Cons_pool_size], 0, Cons_segment_size);
  351. Cons_pool_size += Cons_segment_size;
  352. Cons_segment_size = Cons_pool_size / 2;
  353. }
  354. static void new_vec_segment(void) {
  355. Vectors = realloc(Vectors, sizeof(cell) *
  356. (Vec_pool_size + Vec_segment_size));
  357. if (Vectors == NULL)
  358. s9_fatal("new_vec_segment: out of physical memory");
  359. memset(&Vectors[Vec_pool_size], 0, Vec_segment_size * sizeof(cell));
  360. Vec_pool_size += Vec_segment_size;
  361. Vec_segment_size = Vec_pool_size / 2;
  362. }
  363. /*
  364. * Mark nodes which can be accessed through N.
  365. * Using the Deutsch/Schorr/Waite pointer reversal algorithm.
  366. * S0: M==0, S==0, unvisited, process CAR (vectors: process 1st slot);
  367. * S1: M==1, S==1, CAR visited, process CDR (vectors: process next slot);
  368. * S2: M==1, S==0, completely visited, return to parent.
  369. */
  370. static void mark(cell n) {
  371. cell p, parent, *v;
  372. int i;
  373. parent = NIL;
  374. while (1) {
  375. if (s9_special_p(n) || (Tag[n] & S9_MARK_TAG)) {
  376. if (parent == NIL)
  377. break;
  378. if (Tag[parent] & S9_VECTOR_TAG) { /* S1 --> S1|done */
  379. i = vector_index(parent);
  380. v = vector(parent);
  381. if (Tag[parent] & S9_STATE_TAG &&
  382. i+1 < vector_len(parent)
  383. ) { /* S1 --> S1 */
  384. p = v[i+1];
  385. v[i+1] = v[i];
  386. v[i] = n;
  387. n = p;
  388. vector_index(parent) = i+1;
  389. }
  390. else { /* S1 --> done */
  391. Tag[parent] &= ~S9_STATE_TAG;
  392. p = parent;
  393. parent = v[i];
  394. v[i] = n;
  395. n = p;
  396. }
  397. }
  398. else if (Tag[parent] & S9_STATE_TAG) { /* S1 --> S2 */
  399. p = cdr(parent);
  400. cdr(parent) = car(parent);
  401. car(parent) = n;
  402. Tag[parent] &= ~S9_STATE_TAG;
  403. /* Tag[parent] |= S9_MARK_TAG; */
  404. n = p;
  405. }
  406. else { /* S2 --> done */
  407. p = parent;
  408. parent = cdr(p);
  409. cdr(p) = n;
  410. n = p;
  411. }
  412. }
  413. else if (Tag[n] & S9_VECTOR_TAG) { /* S0 --> S1|S2 */
  414. Tag[n] |= S9_MARK_TAG;
  415. /* Tag[n] &= ~S9_STATE_TAG; */
  416. vector_link(n) = n;
  417. if (car(n) == T_VECTOR && vector_len(n) != 0) {
  418. Tag[n] |= S9_STATE_TAG;
  419. vector_index(n) = 0;
  420. v = vector(n);
  421. p = v[0];
  422. v[0] = parent;
  423. parent = n;
  424. n = p;
  425. }
  426. }
  427. else if (Tag[n] & S9_ATOM_TAG) { /* S0 --> S2 */
  428. if (input_port_p(n) || output_port_p(n))
  429. Port_flags[port_no(n)] |= S9_USED_TAG;
  430. p = cdr(n);
  431. cdr(n) = parent;
  432. /*Tag[n] &= ~S9_STATE_TAG;*/
  433. parent = n;
  434. n = p;
  435. Tag[parent] |= S9_MARK_TAG;
  436. }
  437. else { /* S0 --> S1 */
  438. p = car(n);
  439. car(n) = parent;
  440. Tag[n] |= S9_MARK_TAG;
  441. parent = n;
  442. n = p;
  443. Tag[parent] |= S9_STATE_TAG;
  444. }
  445. }
  446. }
  447. /* Mark and sweep GC. */
  448. int s9_gc(void) {
  449. int i, k, sk = 0;
  450. char buf[100];
  451. if (Run_stats)
  452. s9_count(&Collections);
  453. for (i=0; i<S9_MAX_PORTS; i++) {
  454. if (Port_flags[i] & S9_LOCK_TAG)
  455. Port_flags[i] |= S9_USED_TAG;
  456. else
  457. Port_flags[i] &= ~S9_USED_TAG;
  458. }
  459. if (GC_stack && *GC_stack != NIL) {
  460. sk = string_len(*GC_stack);
  461. string_len(*GC_stack) = (1 + *GC_stkptr) * sizeof(cell);
  462. }
  463. for (i=0; GC_int_roots[i] != NULL; i++) {
  464. mark(*GC_int_roots[i]);
  465. }
  466. if (GC_ext_roots) {
  467. for (i=0; GC_ext_roots[i] != NULL; i++)
  468. mark(*GC_ext_roots[i]);
  469. }
  470. if (GC_stack && *GC_stack != NIL) {
  471. string_len(*GC_stack) = sk;
  472. }
  473. k = 0;
  474. Free_list = NIL;
  475. for (i=0; i<Cons_pool_size; i++) {
  476. if (!(Tag[i] & S9_MARK_TAG)) {
  477. cdr(i) = Free_list;
  478. Free_list = i;
  479. k++;
  480. }
  481. else {
  482. Tag[i] &= ~S9_MARK_TAG;
  483. }
  484. }
  485. for (i=0; i<S9_MAX_PORTS; i++) {
  486. if (!(Port_flags[i] & S9_USED_TAG) && Ports[i] != NULL) {
  487. fclose(Ports[i]);
  488. Ports[i] = NULL;
  489. }
  490. }
  491. if (Verbose_GC > 1) {
  492. sprintf(buf, "GC: %d nodes reclaimed", k);
  493. s9_prints(buf); nl();
  494. s9_flush();
  495. }
  496. return k;
  497. }
  498. /* Allocate a fresh node and initialize with PCAR,PCDR,PTAG. */
  499. cell s9_cons3(cell pcar, cell pcdr, int ptag) {
  500. cell n;
  501. int k;
  502. char buf[100];
  503. if (Run_stats) {
  504. s9_count(&Nodes);
  505. if ( Cons_stats &&
  506. 0 == (ptag & (S9_ATOM_TAG|S9_VECTOR_TAG|S9_PORT_TAG))
  507. )
  508. s9_count(&Conses);
  509. }
  510. if (Free_list == NIL) {
  511. if (ptag == 0)
  512. Tmp_car = pcar;
  513. if (!(ptag & S9_VECTOR_TAG))
  514. Tmp_cdr = pcdr;
  515. k = s9_gc();
  516. /*
  517. * Performance increases dramatically if we
  518. * do not wait for the pool to run dry.
  519. * In fact, don't even let it come close to that.
  520. */
  521. if (k < Cons_pool_size / 2) {
  522. if ( Node_limit &&
  523. Cons_pool_size + Cons_segment_size
  524. > Node_limit
  525. ) {
  526. if (Mem_error_handler)
  527. (*Mem_error_handler)(1);
  528. else
  529. s9_fatal("s9_cons3: hit memory limit");
  530. }
  531. else {
  532. new_cons_segment();
  533. if (Verbose_GC) {
  534. sprintf(buf,
  535. "GC: new segment,"
  536. " nodes = %d,"
  537. " next segment = %d",
  538. Cons_pool_size,
  539. Cons_segment_size);
  540. s9_prints(buf); nl();
  541. s9_flush();
  542. }
  543. s9_gc();
  544. }
  545. }
  546. Tmp_car = Tmp_cdr = NIL;
  547. }
  548. if (Free_list == NIL)
  549. s9_fatal(
  550. "s9_cons3: failed to recover from low memory condition");
  551. n = Free_list;
  552. Free_list = cdr(Free_list);
  553. car(n) = pcar;
  554. cdr(n) = pcdr;
  555. Tag[n] = ptag;
  556. return n;
  557. }
  558. /* Mark all vectors unused */
  559. static void unmark_vectors(void) {
  560. int p, k, link;
  561. p = 0;
  562. while (p < Free_vecs) {
  563. link = p;
  564. k = Vectors[p + RAW_VECTOR_SIZE];
  565. p += vector_size(k);
  566. Vectors[link] = NIL;
  567. }
  568. }
  569. /* In situ vector pool garbage collection and compaction */
  570. int s9_gcv(void) {
  571. int v, k, to, from;
  572. char buf[100];
  573. unmark_vectors();
  574. s9_gc(); /* re-mark live vectors */
  575. to = from = 0;
  576. while (from < Free_vecs) {
  577. v = Vectors[from + RAW_VECTOR_SIZE];
  578. k = vector_size(v);
  579. if (Vectors[from + RAW_VECTOR_LINK] != NIL) {
  580. if (to != from) {
  581. memmove(&Vectors[to], &Vectors[from],
  582. k * sizeof(cell));
  583. cdr(Vectors[to + RAW_VECTOR_LINK]) =
  584. to + RAW_VECTOR_DATA;
  585. }
  586. to += k;
  587. }
  588. from += k;
  589. }
  590. k = Free_vecs - to;
  591. if (Verbose_GC > 1) {
  592. sprintf(buf, "GC: gcv: %d cells reclaimed", k);
  593. s9_prints(buf); nl();
  594. s9_flush();
  595. }
  596. Free_vecs = to;
  597. return k;
  598. }
  599. /* Allocate vector from pool */
  600. cell s9_new_vec(cell type, int size) {
  601. cell n;
  602. int i, v, wsize;
  603. char buf[100];
  604. wsize = vector_size(size);
  605. if (Run_stats) {
  606. s9_countn(&Vecspace, wsize);
  607. }
  608. if (Free_vecs + wsize >= Vec_pool_size) {
  609. s9_gcv();
  610. while ( Free_vecs + wsize >=
  611. Vec_pool_size - Vec_pool_size / 2
  612. ) {
  613. if ( Vector_limit &&
  614. Vec_pool_size + Vec_segment_size
  615. > Vector_limit
  616. ) {
  617. if (Mem_error_handler)
  618. (*Mem_error_handler)(2);
  619. else
  620. s9_fatal("new_vec: hit memory limit");
  621. break;
  622. }
  623. else {
  624. new_vec_segment();
  625. s9_gcv();
  626. if (Verbose_GC) {
  627. sprintf(buf,
  628. "GC: new_vec: new segment,"
  629. " cells = %d",
  630. Vec_pool_size);
  631. s9_prints(buf); nl();
  632. s9_flush();
  633. }
  634. }
  635. }
  636. }
  637. if (Free_vecs + wsize >= Vec_pool_size)
  638. s9_fatal(
  639. "new_vec: failed to recover from low memory condition");
  640. v = Free_vecs;
  641. Free_vecs += wsize;
  642. n = s9_cons3(type, v + RAW_VECTOR_DATA, S9_VECTOR_TAG);
  643. Vectors[v + RAW_VECTOR_LINK] = n;
  644. Vectors[v + RAW_VECTOR_INDEX] = 0;
  645. Vectors[v + RAW_VECTOR_SIZE] = size;
  646. if (type == T_VECTOR) {
  647. for (i = RAW_VECTOR_DATA; i<wsize; i++)
  648. Vectors[v+i] = UNDEFINED;
  649. }
  650. return n;
  651. }
  652. /* Pop K nodes off the Stack, return last one. */
  653. cell s9_unsave(int k) {
  654. cell n = NIL; /*LINT*/
  655. while (k) {
  656. if (Stack == NIL)
  657. s9_fatal("s9_unsave: stack underflow");
  658. n = car(Stack);
  659. Stack = cdr(Stack);
  660. k--;
  661. }
  662. return n;
  663. }
  664. static unsigned hash(char *s) {
  665. unsigned int h = 0;
  666. while (*s) h = ((h<<5)+h) ^ *s++;
  667. return h;
  668. }
  669. static int hash_size(int n) {
  670. if (n < 47) return 47;
  671. if (n < 97) return 97;
  672. if (n < 199) return 199;
  673. if (n < 499) return 499;
  674. if (n < 997) return 997;
  675. if (n < 9973) return 9973;
  676. if (n < 19997) return 19997;
  677. return 39989;
  678. }
  679. #define intval(x) cadr(x)
  680. static void rehash_symbols(void) {
  681. unsigned int i;
  682. cell *v, n, p, new;
  683. unsigned int h, k;
  684. if (NIL == Symhash)
  685. k = hash_size(s9_length(Symbols));
  686. else
  687. k = hash_size(intval(vector(Symhash)[0]));
  688. Symhash = s9_new_vec(T_VECTOR, (k+1) * sizeof(cell));
  689. v = vector(Symhash);
  690. for (i=1; i<=k; i++) v[i] = NIL;
  691. i = 0;
  692. for (p = Symbols; p != NIL; p = cdr(p)) {
  693. h = hash(symbol_name(car(p)));
  694. n = cons(car(p), NIL);
  695. n = cons(n, vector(Symhash)[h%k+1]);
  696. vector(Symhash)[h%k+1] = n;
  697. i++;
  698. }
  699. new = s9_make_integer(i);
  700. vector(Symhash)[0] = new;
  701. }
  702. void add_symhash(cell x) {
  703. cell n, new;
  704. unsigned int h, i, k;
  705. if (NIL == Symhash) {
  706. rehash_symbols();
  707. return;
  708. }
  709. i = intval(vector(Symhash)[0]);
  710. k = vector_len(Symhash)-1;
  711. if (i > k) {
  712. rehash_symbols();
  713. return;
  714. }
  715. h = hash(symbol_name(x));
  716. n = cons(x, NIL);
  717. n = cons(n, vector(Symhash)[h%k+1]);
  718. vector(Symhash)[h%k+1] = n;
  719. new = s9_make_integer(i+1);
  720. vector(Symhash)[0] = new;
  721. }
  722. cell s9_find_symbol(char *s) {
  723. unsigned int h, k;
  724. cell n;
  725. if (NIL == Symhash) return NIL;
  726. k = vector_len(Symhash)-1;
  727. h = hash(s);
  728. for (n = vector(Symhash)[h%k+1]; n != NIL; n = cdr(n))
  729. if (!strcmp(s, symbol_name(caar(n))))
  730. return caar(n);
  731. return NIL;
  732. }
  733. /*
  734. cell s9_find_symbol(char *s) {
  735. cell y;
  736. y = Symbols;
  737. while (y != NIL) {
  738. if (!strcmp(symbol_name(car(y)), s))
  739. return car(y);
  740. y = cdr(y);
  741. }
  742. return NIL;
  743. }
  744. */
  745. cell s9_make_symbol(char *s, int k) {
  746. cell n;
  747. n = s9_new_vec(T_SYMBOL, k+1);
  748. strcpy(symbol_name(n), s);
  749. return n;
  750. }
  751. cell s9_intern_symbol(cell y) {
  752. Symbols = cons(y, Symbols);
  753. add_symhash(y);
  754. return y;
  755. }
  756. cell s9_symbol_table(void) {
  757. return Symbols;
  758. }
  759. cell s9_symbol_ref(char *s) {
  760. cell y, new;
  761. y = s9_find_symbol(s);
  762. if (y != NIL)
  763. return y;
  764. new = s9_make_symbol(s, strlen(s));
  765. return s9_intern_symbol(new);
  766. }
  767. cell s9_make_string(char *s, int k) {
  768. cell n;
  769. if (0 == k) return Nullstr;
  770. n = s9_new_vec(T_STRING, k+1);
  771. strncpy(string(n), s, k+1);
  772. return n;
  773. }
  774. cell s9_make_vector(int k) {
  775. if (0 == k) return Nullvec;
  776. return s9_new_vec(T_VECTOR, k * sizeof(cell));
  777. }
  778. cell s9_mkfix(int v) {
  779. cell n;
  780. n = new_atom(v, NIL);
  781. return new_atom(T_FIXNUM, n);
  782. }
  783. cell s9_make_integer(cell i) {
  784. cell n;
  785. switch (i) {
  786. case 0: return Zero;
  787. case 1: return One;
  788. case 2: return Two;
  789. case 10: return Ten;
  790. default:
  791. n = new_atom(i, NIL);
  792. return new_atom(T_INTEGER, n);
  793. }
  794. }
  795. static cell make_init_integer(cell i) {
  796. cell n;
  797. n = new_atom(i, NIL);
  798. return new_atom(T_INTEGER, n);
  799. }
  800. cell s9_make_char(int x) {
  801. cell n;
  802. if (' ' == x) return Blank;
  803. n = new_atom(x & 0xff, NIL);
  804. return new_atom(T_CHAR, n);
  805. }
  806. static cell real_normalize(cell x);
  807. static cell S9_make_quick_real(int flags, cell exp, cell mant) {
  808. cell n;
  809. n = new_atom(exp, mant);
  810. n = new_atom(flags, n);
  811. n = new_atom(T_REAL, n);
  812. return n;
  813. }
  814. cell S9_make_real(int flags, cell exp, cell mant) {
  815. cell r;
  816. prot(mant);
  817. r = S9_make_quick_real(flags, exp, mant);
  818. r = real_normalize(r);
  819. unprot(1);
  820. return r;
  821. }
  822. cell s9_make_real(int sign, cell exp, cell mant) {
  823. cell m;
  824. int i;
  825. i = 0;
  826. for (m = cdr(mant); m != NIL; m = cdr(m))
  827. i++;
  828. if (i > S9_MANTISSA_SIZE)
  829. return UNDEFINED;
  830. return S9_make_real(sign < 0? REAL_NEGATIVE: 0, exp, cdr(mant));
  831. }
  832. static void grow_primitives(void) {
  833. Max_prims += S9_PRIM_SEG_SIZE;
  834. Primitives = (S9_PRIM *) realloc(Primitives,
  835. sizeof(S9_PRIM) * Max_prims);
  836. if (Primitives == NULL)
  837. s9_fatal("grow_primitives: out of physical memory");
  838. }
  839. cell s9_make_primitive(S9_PRIM *p) {
  840. cell n;
  841. n = new_atom(Last_prim, NIL);
  842. n = new_atom(T_PRIMITIVE, n);
  843. if (Last_prim >= Max_prims)
  844. grow_primitives();
  845. memcpy(&Primitives[Last_prim], p, sizeof(S9_PRIM));
  846. Last_prim++;
  847. return n;
  848. }
  849. cell s9_make_port(int portno, cell type) {
  850. cell n;
  851. int pf;
  852. pf = Port_flags[portno];
  853. Port_flags[portno] |= S9_LOCK_TAG;
  854. n = new_atom(portno, NIL);
  855. n = s9_cons3(type, n, S9_ATOM_TAG|S9_PORT_TAG);
  856. Port_flags[portno] = pf;
  857. return n;
  858. }
  859. cell s9_string_to_symbol(cell x) {
  860. cell y, n, k;
  861. y = s9_find_symbol(string(x));
  862. if (y != NIL)
  863. return y;
  864. /*
  865. * Cannot pass content to s9_make_symbol(), because
  866. * string(x) may move during GC.
  867. */
  868. k = string_len(x);
  869. n = s9_make_symbol("", k-1);
  870. memcpy(symbol_name(n), string(x), k);
  871. return s9_intern_symbol(n);
  872. }
  873. cell s9_symbol_to_string(cell x) {
  874. cell n, k;
  875. /*
  876. * Cannot pass name to s9_make_string(), because
  877. * symbol_name(x) may move during GC.
  878. */
  879. k = symbol_len(x);
  880. n = s9_make_string("", k-1);
  881. memcpy(string(n), symbol_name(x), k);
  882. return n;
  883. }
  884. cell s9_copy_string(cell x) {
  885. cell n, k;
  886. /*
  887. * See s9_string_to_symbol(), above.
  888. */
  889. k = string_len(x);
  890. n = s9_make_string("", k-1);
  891. memcpy(string(n), string(x), k);
  892. return n;
  893. }
  894. /*
  895. * Miscellanea
  896. */
  897. int s9_length(cell n) {
  898. int k;
  899. for (k = 0; n != NIL; n = cdr(n))
  900. k++;
  901. return k;
  902. }
  903. int s9_conses(cell n) {
  904. int k;
  905. for (k = 0; pair_p(n); n = cdr(n))
  906. k++;
  907. return k;
  908. }
  909. cell s9_flat_copy(cell n, cell *lastp) {
  910. cell a, m, last, new;
  911. if (n == NIL) {
  912. if (lastp != NULL)
  913. lastp[0] = NIL;
  914. return NIL;
  915. }
  916. m = s9_cons3(NIL, NIL, Tag[n]);
  917. prot(m);
  918. a = m;
  919. last = m;
  920. while (n != NIL) {
  921. car(a) = car(n);
  922. last = a;
  923. n = cdr(n);
  924. if (n != NIL) {
  925. new = s9_cons3(NIL, NIL, Tag[n]);
  926. cdr(a) = new;
  927. a = cdr(a);
  928. }
  929. }
  930. unprot(1);
  931. if (lastp != NULL)
  932. lastp[0] = last;
  933. return m;
  934. }
  935. long s9_asctol(char *s) {
  936. while (*s == '0' && s[1])
  937. s++;
  938. return atol(s);
  939. }
  940. static char *ntoa(char *b, cell x, int w) {
  941. char buf[40];
  942. int i = 0, neg = 0;
  943. char *p = &buf[sizeof(buf)-1];
  944. if (x < 0) {
  945. x = -x;
  946. neg = 1;
  947. }
  948. *p = 0;
  949. while (x || i == 0) {
  950. i++;
  951. if (i >= sizeof(buf)-1)
  952. s9_fatal("ntoa: number too big");
  953. p--;
  954. *p = x % 10 + '0';
  955. x = x / 10;
  956. }
  957. while (i < (w-neg) && i < sizeof(buf)-1) {
  958. i++;
  959. p--;
  960. *p = '0';
  961. }
  962. if (neg) {
  963. if (i >= sizeof(buf)-1)
  964. s9_fatal("ntoa: number too big");
  965. p--;
  966. *p = '-';
  967. }
  968. strcpy(b, p);
  969. return b;
  970. }
  971. cell s9_argv_to_list(char **argv) {
  972. int i;
  973. cell a, n;
  974. if (argv[0] == NULL) return NIL;
  975. a = cons(NIL, NIL);
  976. prot(a);
  977. for (i = 0; argv[i] != NULL; i++) {
  978. n = s9_make_string(argv[i], strlen(argv[i]));
  979. car(a) = n;
  980. if (argv[i+1] != NULL) {
  981. n = cons(NIL, NIL);
  982. cdr(a) = n;
  983. a = cdr(a);
  984. }
  985. }
  986. return unprot(1);
  987. }
  988. #ifdef plan9
  989. int system(char *cmd) {
  990. Waitmsg *w;
  991. int pid;
  992. char *argv[] = { "/bin/rc", "-c", cmd, NULL };
  993. switch (pid = fork()) {
  994. case -1:
  995. return -1;
  996. case 0:
  997. exec(argv[0], argv);
  998. bye(1);
  999. default:
  1000. while ((w = wait()) != NULL) {
  1001. if (w->pid == pid) {
  1002. if (w->msg[0] == 0) {
  1003. free(w);
  1004. return 0;
  1005. }
  1006. free(w);
  1007. return 1;
  1008. }
  1009. free(w);
  1010. }
  1011. return 0;
  1012. }
  1013. }
  1014. #endif /* plan9 */
  1015. /*
  1016. * Bignums
  1017. */
  1018. cell s9_bignum_abs(cell a) {
  1019. cell n;
  1020. prot(a);
  1021. n = new_atom(labs(cadr(a)), cddr(a));
  1022. n = new_atom(T_INTEGER, n);
  1023. unprot(1);
  1024. return n;
  1025. }
  1026. cell s9_bignum_negate(cell a) {
  1027. cell n;
  1028. prot(a);
  1029. n = new_atom(-cadr(a), cddr(a));
  1030. n = new_atom(T_INTEGER, n);
  1031. unprot(1);
  1032. return n;
  1033. }
  1034. static cell reverse_segments(cell n) {
  1035. cell m;
  1036. m = NIL;
  1037. while (n != NIL) {
  1038. m = new_atom(car(n), m);
  1039. n = cdr(n);
  1040. }
  1041. return m;
  1042. }
  1043. int s9_bignum_even_p(cell a) {
  1044. while (cdr(a) != NIL)
  1045. a = cdr(a);
  1046. return car(a) % 2 == 0;
  1047. }
  1048. cell s9_bignum_add(cell a, cell b);
  1049. cell s9_bignum_subtract(cell a, cell b);
  1050. static cell Bignum_add(cell a, cell b) {
  1051. cell fa, fb, result, r;
  1052. int carry;
  1053. if (bignum_negative_p(a)) {
  1054. if (bignum_negative_p(b)) {
  1055. /* -A+-B --> -(|A|+|B|) */
  1056. a = s9_bignum_abs(a);
  1057. prot(a);
  1058. a = s9_bignum_add(a, s9_bignum_abs(b));
  1059. unprot(1);
  1060. return s9_bignum_negate(a);
  1061. }
  1062. else {
  1063. /* -A+B --> B-|A| */
  1064. return s9_bignum_subtract(b, s9_bignum_abs(a));
  1065. }
  1066. }
  1067. else if (bignum_negative_p(b)) {
  1068. /* A+-B --> A-|B| */
  1069. return s9_bignum_subtract(a, s9_bignum_abs(b));
  1070. }
  1071. /* A+B */
  1072. a = reverse_segments(cdr(a));
  1073. prot(a);
  1074. b = reverse_segments(cdr(b));
  1075. prot(b);
  1076. carry = 0;
  1077. result = NIL;
  1078. prot(result);
  1079. while (a != NIL || b != NIL || carry) {
  1080. fa = a == NIL? 0: car(a);
  1081. fb = b == NIL? 0: car(b);
  1082. r = fa + fb + carry;
  1083. carry = 0;
  1084. if (r >= S9_INT_SEG_LIMIT) {
  1085. r -= S9_INT_SEG_LIMIT;
  1086. carry = 1;
  1087. }
  1088. result = new_atom(r, result);
  1089. pref(0) = result;
  1090. if (a != NIL) a = cdr(a);
  1091. if (b != NIL) b = cdr(b);
  1092. }
  1093. unprot(3);
  1094. return new_atom(T_INTEGER, result);
  1095. }
  1096. cell s9_bignum_add(cell a, cell b) {
  1097. Tmp = b;
  1098. prot(a);
  1099. prot(b);
  1100. Tmp = NIL;
  1101. a = Bignum_add(a, b);
  1102. unprot(2);
  1103. return a;
  1104. }
  1105. int s9_bignum_less_p(cell a, cell b) {
  1106. int ka, kb, neg_a, neg_b;
  1107. neg_a = bignum_negative_p(a);
  1108. neg_b = bignum_negative_p(b);
  1109. if (neg_a && !neg_b) return 1;
  1110. if (!neg_a && neg_b) return 0;
  1111. ka = s9_length(a);
  1112. kb = s9_length(b);
  1113. if (ka < kb) return neg_a? 0: 1;
  1114. if (ka > kb) return neg_a? 1: 0;
  1115. Tmp = b;
  1116. a = s9_bignum_abs(a);
  1117. prot(a);
  1118. b = s9_bignum_abs(b);
  1119. unprot(1);
  1120. Tmp = NIL;
  1121. a = cdr(a);
  1122. b = cdr(b);
  1123. while (a != NIL) {
  1124. if (car(a) < car(b)) return neg_a? 0: 1;
  1125. if (car(a) > car(b)) return neg_a? 1: 0;
  1126. a = cdr(a);
  1127. b = cdr(b);
  1128. }
  1129. return 0;
  1130. }
  1131. int s9_bignum_equal_p(cell a, cell b) {
  1132. a = cdr(a);
  1133. b = cdr(b);
  1134. while (a != NIL && b != NIL) {
  1135. if (car(a) != car(b))
  1136. return 0;
  1137. a = cdr(a);
  1138. b = cdr(b);
  1139. }
  1140. return a == NIL && b == NIL;
  1141. }
  1142. static cell Bignum_subtract(cell a, cell b) {
  1143. cell fa, fb, result, r;
  1144. int borrow;
  1145. if (bignum_negative_p(a)) {
  1146. if (bignum_negative_p(b)) {
  1147. /* -A--B --> -A+|B| --> |B|-|A| */
  1148. a = s9_bignum_abs(a);
  1149. prot(a);
  1150. a = s9_bignum_subtract(s9_bignum_abs(b), a);
  1151. unprot(1);
  1152. return a;
  1153. }
  1154. else {
  1155. /* -A-B --> -(|A|+B) */
  1156. return s9_bignum_negate(
  1157. s9_bignum_add(s9_bignum_abs(a), b));
  1158. }
  1159. }
  1160. else if (bignum_negative_p(b)) {
  1161. /* A--B --> A+|B| */
  1162. return s9_bignum_add(a, s9_bignum_abs(b));
  1163. }
  1164. /* A-B, A<B --> -(B-A) */
  1165. if (s9_bignum_less_p(a, b))
  1166. return s9_bignum_negate(s9_bignum_subtract(b, a));
  1167. /* A-B, A>=B */
  1168. a = reverse_segments(cdr(a));
  1169. prot(a);
  1170. b = reverse_segments(cdr(b));
  1171. prot(b);
  1172. borrow = 0;
  1173. result = NIL;
  1174. prot(result);
  1175. while (a != NIL || b != NIL || borrow) {
  1176. fa = a == NIL? 0: car(a);
  1177. fb = b == NIL? 0: car(b);
  1178. r = fa - fb - borrow;
  1179. borrow = 0;
  1180. if (r < 0) {
  1181. r += S9_INT_SEG_LIMIT;
  1182. borrow = 1;
  1183. }
  1184. result = new_atom(r, result);
  1185. pref(0) = result;
  1186. if (a != NIL) a = cdr(a);
  1187. if (b != NIL) b = cdr(b);
  1188. }
  1189. unprot(3);
  1190. while (car(result) == 0 && cdr(result) != NIL)
  1191. result = cdr(result);
  1192. return new_atom(T_INTEGER, result);
  1193. }
  1194. cell s9_bignum_subtract(cell a, cell b) {
  1195. Tmp = b;
  1196. prot(a);
  1197. prot(b);
  1198. Tmp = NIL;
  1199. a = Bignum_subtract(a, b);
  1200. unprot(2);
  1201. return a;
  1202. }
  1203. cell s9_bignum_shift_left(cell a, int fill) {
  1204. cell r, c, result;
  1205. int carry;
  1206. prot(a);
  1207. a = reverse_segments(cdr(a));
  1208. prot(a);
  1209. carry = fill;
  1210. result = NIL;
  1211. prot(result);
  1212. while (a != NIL) {
  1213. if (car(a) >= S9_INT_SEG_LIMIT/10) {
  1214. c = car(a) / (S9_INT_SEG_LIMIT/10);
  1215. r = car(a) % (S9_INT_SEG_LIMIT/10) * 10;
  1216. r += carry;
  1217. carry = c;
  1218. }
  1219. else {
  1220. r = car(a) * 10 + carry;
  1221. carry = 0;
  1222. }
  1223. result = new_atom(r, result);
  1224. pref(0) = result;
  1225. a = cdr(a);
  1226. }
  1227. if (carry)
  1228. result = new_atom(carry, result);
  1229. result = new_atom(T_INTEGER, result);
  1230. unprot(3);
  1231. return result;
  1232. }
  1233. /* Result: (a/10 . a%10) */
  1234. cell s9_bignum_shift_right(cell a) {
  1235. cell r, c, result;
  1236. int carry;
  1237. prot(a);
  1238. a = cdr(a);
  1239. prot(a);
  1240. carry = 0;
  1241. result = NIL;
  1242. prot(result);
  1243. while (a != NIL) {
  1244. c = car(a) % 10;
  1245. r = car(a) / 10;
  1246. r += carry * (S9_INT_SEG_LIMIT/10);
  1247. carry = c;
  1248. result = new_atom(r, result);
  1249. pref(0) = result;
  1250. a = cdr(a);
  1251. }
  1252. result = reverse_segments(result);
  1253. if (car(result) == 0 && cdr(result) != NIL)
  1254. result = cdr(result);
  1255. result = new_atom(T_INTEGER, result);
  1256. pref(0) = result;
  1257. carry = s9_make_integer(carry);
  1258. result = cons(result, carry);
  1259. unprot(3);
  1260. return result;
  1261. }
  1262. cell s9_bignum_multiply(cell a, cell b) {
  1263. int neg;
  1264. cell r, i, result;
  1265. Tmp = b;
  1266. prot(a);
  1267. prot(b);
  1268. Tmp = NIL;
  1269. neg = bignum_negative_p(a) != bignum_negative_p(b);
  1270. a = s9_bignum_abs(a);
  1271. prot(a);
  1272. b = s9_bignum_abs(b);
  1273. prot(b);
  1274. result = Zero;
  1275. prot(result);
  1276. while (!bignum_zero_p(a)) {
  1277. r = s9_bignum_shift_right(a);
  1278. i = caddr(r);
  1279. a = car(r);
  1280. pref(2) = a;
  1281. while (i) {
  1282. if (Abort_flag) {
  1283. unprot(5);
  1284. return Zero;
  1285. }
  1286. result = s9_bignum_add(result, b);
  1287. pref(0) = result;
  1288. i--;
  1289. }
  1290. b = s9_bignum_shift_left(b, 0);
  1291. pref(1) = b;
  1292. }
  1293. if (neg)
  1294. result = s9_bignum_negate(result);
  1295. unprot(5);
  1296. return result;
  1297. }
  1298. /*
  1299. * Equalize A and B, e.g.:
  1300. * A=123, B=12345 --> 12300, 100
  1301. * Return (scaled-a . scaling-factor)
  1302. */
  1303. static cell bignum_equalize(cell a, cell b) {
  1304. cell r, f, r0, f0;
  1305. r0 = a;
  1306. prot(r0);
  1307. f0 = One;
  1308. prot(f0);
  1309. r = r0;
  1310. prot(r);
  1311. f = f0;
  1312. prot(f);
  1313. while (s9_bignum_less_p(r, b)) {
  1314. pref(3) = r0 = r;
  1315. pref(2) = f0 = f;
  1316. r = s9_bignum_shift_left(r, 0);
  1317. pref(1) = r;
  1318. f = s9_bignum_shift_left(f, 0);
  1319. pref(0) = f;
  1320. }
  1321. unprot(4);
  1322. return cons(r0, f0);
  1323. }
  1324. /* Result: (a/b . a%b) */
  1325. static cell Bignum_divide(cell a, cell b) {
  1326. int neg, neg_a;
  1327. cell result, f;
  1328. int i;
  1329. cell c, c0;
  1330. neg_a = bignum_negative_p(a);
  1331. neg = neg_a != bignum_negative_p(b);
  1332. a = s9_bignum_abs(a);
  1333. prot(a);
  1334. b = s9_bignum_abs(b);
  1335. prot(b);
  1336. if (s9_bignum_less_p(a, b)) {
  1337. if (neg_a)
  1338. a = s9_bignum_negate(a);
  1339. unprot(2);
  1340. return cons(Zero, a);
  1341. }
  1342. b = bignum_equalize(b, a);
  1343. pref(1) = b;
  1344. pref(0) = a;
  1345. c = NIL;
  1346. prot(c);
  1347. c0 = NIL;
  1348. prot(c0);
  1349. f = cdr(b);
  1350. b = car(b);
  1351. pref(3) = b;
  1352. prot(f);
  1353. result = Zero;
  1354. prot(result);
  1355. while (!bignum_zero_p(f)) {
  1356. c = Zero;
  1357. pref(3) = c;
  1358. pref(2) = c0 = c;
  1359. i = 0;
  1360. while (!s9_bignum_less_p(a, c)) {
  1361. pref(2) = c0 = c;
  1362. c = s9_bignum_add(c, b);
  1363. pref(3) = c;
  1364. i++;
  1365. }
  1366. result = s9_bignum_shift_left(result, i-1);
  1367. pref(0) = result;
  1368. a = s9_bignum_subtract(a, c0);
  1369. pref(4) = a;
  1370. f = s9_bignum_shift_right(f);
  1371. f = car(f);
  1372. pref(1) = f;
  1373. b = s9_bignum_shift_right(b);
  1374. b = car(b);
  1375. pref(5) = b;
  1376. }
  1377. if (neg)
  1378. result = s9_bignum_negate(result);
  1379. pref(0) = result;
  1380. if (neg_a)
  1381. a = s9_bignum_negate(a);
  1382. unprot(6);
  1383. return cons(result, a);
  1384. }
  1385. cell s9_bignum_divide(cell a, cell b) {
  1386. if (bignum_zero_p(b))
  1387. return UNDEFINED;
  1388. Tmp = b;
  1389. prot(a);
  1390. prot(b);
  1391. Tmp = NIL;
  1392. a = Bignum_divide(a, b);
  1393. unprot(2);
  1394. return a;
  1395. }
  1396. /*
  1397. * Real Number Arithmetics
  1398. */
  1399. static cell count_digits(cell m) {
  1400. int k;
  1401. cell x;
  1402. x = car(m);
  1403. k = 0;
  1404. while (x != 0) {
  1405. x /= 10;
  1406. k++;
  1407. }
  1408. k = k==0? 1: k;
  1409. m = cdr(m);
  1410. while (m != NIL) {
  1411. k += S9_DIGITS_PER_CELL;
  1412. m = cdr(m);
  1413. }
  1414. return k;
  1415. }
  1416. cell s9_real_exponent(cell x) {
  1417. if (integer_p(x)) return 0;
  1418. return Real_exponent(x);
  1419. }
  1420. cell s9_real_mantissa(cell x) {
  1421. cell m;
  1422. if (integer_p(x))
  1423. return x;
  1424. m = new_atom(T_INTEGER, Real_mantissa(x));
  1425. if (Real_negative_p(x))
  1426. m = s9_bignum_negate(m);
  1427. return m;
  1428. }
  1429. /*
  1430. * Remove trailing zeros and move the decimal
  1431. * point to the END of the mantissa, e.g.:
  1432. * real_normalize(1.234e0) --> 1234e-3
  1433. *
  1434. * Limit the mantissa to S9_MANTISSA_SEGMENTS
  1435. * machine words. This may cause a loss of
  1436. * precision.
  1437. *
  1438. * Also handle numeric overflow/underflow.
  1439. */
  1440. static cell real_normalize(cell x) {
  1441. cell m, e, r;
  1442. int dgs;
  1443. prot(x);
  1444. e = Real_exponent(x);
  1445. m = new_atom(T_INTEGER, Real_mantissa(x));
  1446. prot(m);
  1447. dgs = count_digits(cdr(m));
  1448. while (dgs > S9_MANTISSA_SIZE) {
  1449. r = s9_bignum_shift_right(m);
  1450. m = car(r);
  1451. pref(0) = m;
  1452. dgs--;
  1453. e++;
  1454. }
  1455. while (!bignum_zero_p(m)) {
  1456. r = s9_bignum_shift_right(m);
  1457. if (!bignum_zero_p(cdr(r)))
  1458. break;
  1459. m = car(r);
  1460. pref(0) = m;
  1461. e++;
  1462. }
  1463. if (bignum_zero_p(m))
  1464. e = 0;
  1465. r = new_atom(e, NIL);
  1466. if (count_digits(r) > S9_DIGITS_PER_CELL) {
  1467. unprot(2);
  1468. return UNDEFINED;
  1469. }
  1470. r = S9_make_quick_real(Real_flags(x), e, cdr(m));
  1471. unprot(2);
  1472. return r;
  1473. }
  1474. cell s9_bignum_to_real(cell a) {
  1475. int e, flags, d;
  1476. cell m, n;
  1477. prot(a);
  1478. m = s9_flat_copy(a, NULL);
  1479. cadr(m) = labs(cadr(m));
  1480. e = 0;
  1481. if (s9_length(cdr(m)) > S9_MANTISSA_SEGMENTS) {
  1482. d = count_digits(cdr(m));
  1483. while (d > S9_MANTISSA_SIZE) {
  1484. m = s9_bignum_shift_right(m);
  1485. m = car(m);
  1486. e++;
  1487. d--;
  1488. }
  1489. }
  1490. flags = bignum_negative_p(a)? REAL_NEGATIVE: 0;
  1491. n = S9_make_quick_real(flags, e, cdr(m));
  1492. n = real_normalize(n);
  1493. unprot(1);
  1494. return n;
  1495. }
  1496. cell s9_real_negate(cell a) {
  1497. if (integer_p(a))
  1498. return s9_bignum_negate(a);
  1499. Tmp = a;
  1500. a = Real_negate(a);
  1501. Tmp = NIL;
  1502. return a;
  1503. }
  1504. cell s9_real_negative_p(cell a) {
  1505. if (integer_p(a))
  1506. return bignum_negative_p(a);
  1507. return Real_negative_p(a);
  1508. }
  1509. cell s9_real_positive_p(cell a) {
  1510. if (integer_p(a))
  1511. return bignum_positive_p(a);
  1512. return Real_positive_p(a);
  1513. }
  1514. cell s9_real_zero_p(cell a) {
  1515. if (integer_p(a))
  1516. return bignum_zero_p(a);
  1517. return Real_zero_p(a);
  1518. }
  1519. cell s9_real_abs(cell a) {
  1520. if (integer_p(a))
  1521. return s9_bignum_abs(a);
  1522. if (Real_negative_p(a)) {
  1523. Tmp = a;
  1524. a = Real_negate(a);
  1525. Tmp = NIL;
  1526. return a;
  1527. }
  1528. return a;
  1529. }
  1530. /*
  1531. * Scale the number R so that it gets exponent DESIRED_E
  1532. * without changing its value. When there is not enough
  1533. * room for scaling the mantissa of R, return UNDEFINED.
  1534. * E.g.: scale_mantissa(1.0e0, -2, 0) --> 100.0e-2
  1535. *
  1536. * Allow the mantissa to grow to MAX_SIZE segments.
  1537. */
  1538. static cell scale_mantissa(cell r, cell desired_e, int max_size) {
  1539. int dgs;
  1540. cell n, e;
  1541. dgs = count_digits(Real_mantissa(r));
  1542. if (max_size && (max_size - dgs < Real_exponent(r) - desired_e))
  1543. return UNDEFINED;
  1544. n = new_atom(T_INTEGER, s9_flat_copy(Real_mantissa(r), NULL));
  1545. prot(n);
  1546. e = Real_exponent(r);
  1547. while (e > desired_e) {
  1548. n = s9_bignum_shift_left(n, 0);
  1549. pref(0) = n;
  1550. e--;
  1551. }
  1552. unprot(1);
  1553. return S9_make_quick_real(Real_flags(r), e, cdr(n));
  1554. }
  1555. static void autoscale(cell *pa, cell *pb) {
  1556. if (Real_exponent(*pa) < Real_exponent(*pb)) {
  1557. *pb = scale_mantissa(*pb, Real_exponent(*pa),
  1558. S9_MANTISSA_SIZE*2);
  1559. return;
  1560. }
  1561. if (Real_exponent(*pa) > Real_exponent(*pb)) {
  1562. *pa = scale_mantissa(*pa, Real_exponent(*pb),
  1563. S9_MANTISSA_SIZE*2);
  1564. }
  1565. }
  1566. cell shift_mantissa(cell m) {
  1567. m = new_atom(T_INTEGER, m);
  1568. prot(m);
  1569. m = s9_bignum_shift_right(m);
  1570. unprot(1);
  1571. return cdar(m);
  1572. }
  1573. static int real_compare(cell a, cell b, int approx) {
  1574. cell ma, mb, d, e;
  1575. int p;
  1576. if (integer_p(a) && integer_p(b))
  1577. return s9_bignum_equal_p(a, b);
  1578. Tmp = b;
  1579. prot(a);
  1580. prot(b);
  1581. Tmp = NIL;
  1582. if (integer_p(a)) {
  1583. a = s9_bignum_to_real(a);
  1584. pref(1) = a;
  1585. }
  1586. if (integer_p(b)) {
  1587. prot(a);
  1588. b = s9_bignum_to_real(b);
  1589. unprot(1);
  1590. pref(0) = b;
  1591. }
  1592. if (Real_zero_p(a) && Real_zero_p(b)) {
  1593. unprot(2);
  1594. return 1;
  1595. }
  1596. if (Real_negative_p(a) != Real_negative_p(b)) {
  1597. unprot(2);
  1598. return 0;
  1599. }
  1600. if (approx) {
  1601. d = s9_real_abs(s9_real_subtract(a, b));
  1602. /* integer magnitudes */
  1603. ma = count_digits(Real_mantissa(a))+Real_exponent(a);
  1604. mb = count_digits(Real_mantissa(b))+Real_exponent(b);
  1605. if (ma != mb) {
  1606. unprot(2);
  1607. return 0;
  1608. }
  1609. p = ma-S9_MANTISSA_SIZE;
  1610. prot(d);
  1611. e = S9_make_quick_real(0, p, cdr(One));
  1612. unprot(3);
  1613. return !s9_real_less_p(e, d);
  1614. }
  1615. unprot(2);
  1616. if (Real_exponent(a) != Real_exponent(b))
  1617. return 0;
  1618. ma = Real_mantissa(a);
  1619. mb = Real_mantissa(b);
  1620. while (ma != NIL && mb != NIL) {
  1621. if (car(ma) != car(mb))
  1622. return 0;
  1623. ma = cdr(ma);
  1624. mb = cdr(mb);
  1625. }
  1626. if (ma != mb)
  1627. return 0;
  1628. return 1;
  1629. }
  1630. int s9_real_equal_p(cell a, cell b) {
  1631. return real_compare(a, b, 0);
  1632. }
  1633. int s9_real_approx_p(cell a, cell b) {
  1634. return real_compare(a, b, 1);
  1635. }
  1636. int s9_real_less_p(cell a, cell b) {
  1637. cell ma, mb;
  1638. int ka, kb, neg;
  1639. int dpa, dpb;
  1640. if (integer_p(a) && integer_p(b))
  1641. return s9_bignum_less_p(a, b);
  1642. Tmp = b;
  1643. prot(a);
  1644. prot(b);
  1645. Tmp = NIL;
  1646. if (integer_p(a))
  1647. a = s9_bignum_to_real(a);
  1648. if (integer_p(b)) {
  1649. prot(a);
  1650. b = s9_bignum_to_real(b);
  1651. unprot(1);
  1652. }
  1653. unprot(2);
  1654. if (Real_negative_p(a) && !Real_negative_p(b)) return 1;
  1655. if (Real_negative_p(b) && !Real_negative_p(a)) return 0;
  1656. if (Real_zero_p(a) && Real_positive_p(b)) return 1;
  1657. if (Real_zero_p(b) && Real_positive_p(a)) return 0;
  1658. neg = Real_negative_p(a);
  1659. dpa = count_digits(Real_mantissa(a)) + Real_exponent(a);
  1660. dpb = count_digits(Real_mantissa(b)) + Real_exponent(b);
  1661. if (dpa < dpb) return neg? 0: 1;
  1662. if (dpa > dpb) return neg? 1: 0;
  1663. Tmp = b;
  1664. prot(a);
  1665. prot(b);
  1666. Tmp = NIL;
  1667. autoscale(&a, &b);
  1668. unprot(2);
  1669. if (a == UNDEFINED) return neg? 1: 0;
  1670. if (b == UNDEFINED) return neg? 0: 1;
  1671. ma = Real_mantissa(a);
  1672. mb = Real_mantissa(b);
  1673. ka = s9_length(ma);
  1674. kb = s9_length(mb);
  1675. if (ka < kb) return 1;
  1676. if (ka > kb) return 0;
  1677. while (ma != NIL) {
  1678. if (car(ma) < car(mb)) return neg? 0: 1;
  1679. if (car(ma) > car(mb)) return neg? 1: 0;
  1680. ma = cdr(ma);
  1681. mb = cdr(mb);
  1682. }
  1683. return 0;
  1684. }
  1685. cell s9_real_add(cell a, cell b) {
  1686. cell r, m, e, aa, ab;
  1687. int flags, nega, negb;
  1688. if (integer_p(a) && integer_p(b))
  1689. return s9_bignum_add(a, b);
  1690. Tmp = b;
  1691. prot(a);
  1692. prot(b);
  1693. Tmp = NIL;
  1694. if (integer_p(a))
  1695. a = s9_bignum_to_real(a);
  1696. prot(a);
  1697. if (integer_p(b))
  1698. b = s9_bignum_to_real(b);
  1699. prot(b);
  1700. if (Real_zero_p(a)) {
  1701. unprot(4);
  1702. return b;
  1703. }
  1704. if (Real_zero_p(b)) {
  1705. unprot(4);
  1706. return a;
  1707. }
  1708. autoscale(&a, &b);
  1709. if (a == UNDEFINED || b == UNDEFINED) {
  1710. ab = s9_real_abs(pref(0));
  1711. prot(ab);
  1712. aa = s9_real_abs(pref(2));
  1713. unprot(1);
  1714. b = unprot(1);
  1715. a = unprot(1);
  1716. unprot(2);
  1717. return s9_real_less_p(aa, ab)? b: a;
  1718. }
  1719. pref(1) = a;
  1720. pref(0) = b;
  1721. e = Real_exponent(a);
  1722. nega = Real_negative_p(a);
  1723. negb = Real_negative_p(b);
  1724. a = new_atom(T_INTEGER, Real_mantissa(a));
  1725. if (nega)
  1726. a = s9_bignum_negate(a);
  1727. pref(1) = a;
  1728. b = new_atom(T_INTEGER, Real_mantissa(b));
  1729. if (negb)
  1730. b = s9_bignum_negate(b);
  1731. pref(0) = b;
  1732. m = s9_bignum_add(a, b);
  1733. flags = bignum_negative_p(m)? REAL_NEGATIVE: 0;
  1734. r = s9_bignum_abs(m);
  1735. r = S9_make_quick_real(flags, e, cdr(r));
  1736. r = real_normalize(r);
  1737. unprot(4);
  1738. return r;
  1739. }
  1740. cell s9_real_subtract(cell a, cell b) {
  1741. cell r;
  1742. Tmp = b;
  1743. prot(a);
  1744. prot(b);
  1745. Tmp = NIL;
  1746. if (integer_p(b))
  1747. b = s9_bignum_negate(b);
  1748. else
  1749. b = Real_negate(b);
  1750. prot(b);
  1751. r = s9_real_add(a, b);
  1752. unprot(3);
  1753. return r;
  1754. }
  1755. cell s9_real_multiply(cell a, cell b) {
  1756. cell r, m, e, ma, mb, ea, eb, neg;
  1757. if (integer_p(a) && integer_p(b))
  1758. return s9_bignum_multiply(a, b);
  1759. Tmp = b;
  1760. prot(a);
  1761. prot(b);
  1762. Tmp = NIL;
  1763. if (integer_p(a))
  1764. a = s9_bignum_to_real(a);
  1765. prot(a);
  1766. if (integer_p(b))
  1767. b = s9_bignum_to_real(b);
  1768. prot(b);
  1769. neg = Real_negative_flag(a) != Real_negative_flag(b);
  1770. ea = Real_exponent(a);
  1771. eb = Real_exponent(b);
  1772. ma = new_atom(T_INTEGER, Real_mantissa(a));
  1773. pref(1) = ma;
  1774. mb = new_atom(T_INTEGER, Real_mantissa(b));
  1775. pref(0) = mb;
  1776. e = ea + eb;
  1777. m = s9_bignum_multiply(ma, mb);
  1778. r = S9_make_quick_real(neg? REAL_NEGATIVE: 0, e, cdr(m));
  1779. r = real_normalize(r);
  1780. unprot(4);
  1781. return r;
  1782. }
  1783. cell s9_real_divide(cell a, cell b) {
  1784. cell r, m, e, ma, mb, ea, eb, neg, div2;
  1785. int nd, dd;
  1786. Tmp = b;
  1787. prot(a);
  1788. prot(b);
  1789. Tmp = NIL;
  1790. if (integer_p(a))
  1791. a = s9_bignum_to_real(a);
  1792. prot(a);
  1793. if (integer_p(b))
  1794. b = s9_bignum_to_real(b);
  1795. prot(b);
  1796. if (Real_zero_p(b)) {
  1797. unprot(4);
  1798. return UNDEFINED;
  1799. }
  1800. if (Real_zero_p(a)) {
  1801. r = S9_make_quick_real(0, 0, cdr(Zero));
  1802. unprot(4);
  1803. return r;
  1804. }
  1805. neg = Real_negative_flag(a) != Real_negative_flag(b);
  1806. ea = Real_exponent(a);
  1807. eb = Real_exponent(b);
  1808. ma = new_atom(T_INTEGER, Real_mantissa(a));
  1809. pref(1) = ma;
  1810. mb = new_atom(T_INTEGER, Real_mantissa(b));
  1811. pref(0) = mb;
  1812. if (bignum_zero_p(mb)) {
  1813. unprot(4);
  1814. return UNDEFINED;
  1815. }
  1816. nd = count_digits(cdr(ma));
  1817. dd = S9_MANTISSA_SIZE + count_digits(cdr(mb));
  1818. while (nd < dd) {
  1819. ma = s9_bignum_shift_left(ma, 0);
  1820. pref(1) = ma;
  1821. nd++;
  1822. ea--;
  1823. }
  1824. e = ea - eb;
  1825. m = s9_bignum_divide(ma, mb);
  1826. prot(m);
  1827. div2 = s9_bignum_abs(mb);
  1828. div2 = s9_bignum_divide(div2, Two);
  1829. div2 = car(div2);
  1830. if (s9_bignum_less_p(div2, cdr(m))) {
  1831. m = s9_bignum_add(car(m), One);
  1832. }
  1833. else {
  1834. m = car(m);
  1835. }
  1836. r = S9_make_quick_real(neg? REAL_NEGATIVE: 0, e, cdr(m));
  1837. r = real_normalize(r);
  1838. unprot(5);
  1839. return r;
  1840. }
  1841. cell s9_real_sqrt(cell x) {
  1842. cell n0, n1;
  1843. int r;
  1844. if (s9_real_negative_p(x))
  1845. return UNDEFINED;
  1846. if (s9_real_zero_p(x))
  1847. return Zero;
  1848. prot(x);
  1849. n0 = x;
  1850. prot(n0);
  1851. while (1) {
  1852. n1 = s9_real_divide(x, n0);
  1853. if (n1 == UNDEFINED)
  1854. break;
  1855. n1 = s9_real_add(n1, n0);
  1856. n1 = s9_real_divide(n1, Two);
  1857. prot(n1);
  1858. r = s9_real_approx_p(n0, n1);
  1859. n0 = unprot(1);
  1860. if (r) {
  1861. break;
  1862. }
  1863. pref(0) = n0;
  1864. }
  1865. unprot(2);
  1866. return n1;
  1867. }
  1868. /*
  1869. * Real power algorithm from
  1870. * http://stackoverflow.com/questions/3518973
  1871. * Thanks, Tom Sirgedas!
  1872. */
  1873. static cell rpower(cell x, cell y, cell prec) {
  1874. cell n, nprec;
  1875. if (Abort_flag)
  1876. return Zero;
  1877. if (s9_real_equal_p(y, One))
  1878. return x;
  1879. if (!s9_real_less_p(y, Ten)) {
  1880. prot(x);
  1881. n = s9_real_divide(y, Two);
  1882. pref(0) = n;
  1883. nprec = s9_real_divide(prec, Two);
  1884. prot(nprec);
  1885. n = rpower(x, n, nprec);
  1886. if (n == UNDEFINED || Abort_flag) {
  1887. unprot(2);
  1888. return UNDEFINED;
  1889. }
  1890. unprot(1);
  1891. pref(0) = n;
  1892. n = s9_real_multiply(n, n);
  1893. unprot(1);
  1894. return n;
  1895. }
  1896. if (!s9_real_less_p(y, One)) {
  1897. y = s9_real_subtract(y, One);
  1898. prot(y);
  1899. n = rpower(x, y, prec);
  1900. if (n == UNDEFINED || Abort_flag) {
  1901. unprot(1);
  1902. return UNDEFINED;
  1903. }
  1904. unprot(1);
  1905. n = s9_real_multiply(x, n);
  1906. return n;
  1907. }
  1908. if (!s9_real_less_p(prec, One))
  1909. return s9_real_sqrt(x);
  1910. y = s9_real_multiply(y, Two);
  1911. prot(y);
  1912. nprec = s9_real_multiply(prec, Two);
  1913. prot(nprec);
  1914. n = rpower(x, y, nprec);
  1915. if (n == UNDEFINED || Abort_flag) {
  1916. unprot(2);
  1917. return UNDEFINED;
  1918. }
  1919. unprot(2);
  1920. return s9_real_sqrt(n);
  1921. }
  1922. static cell npower(cell x, cell y) {
  1923. cell n;
  1924. int even;
  1925. if (Abort_flag)
  1926. return Zero;
  1927. if (s9_real_zero_p(y))
  1928. return One;
  1929. if (s9_real_equal_p(y, One))
  1930. return x;
  1931. prot(x);
  1932. n = s9_bignum_divide(y, Two);
  1933. even = bignum_zero_p(cdr(n));
  1934. pref(0) = n;
  1935. n = npower(x, car(n));
  1936. if (Abort_flag) {
  1937. unprot(1);
  1938. return Zero;
  1939. }
  1940. pref(0) = n;
  1941. n = s9_real_multiply(n, n);
  1942. pref(0) = n;
  1943. if (!even) {
  1944. n = s9_real_multiply(x, n);
  1945. pref(0) = n;
  1946. }
  1947. unprot(1);
  1948. return n;
  1949. }
  1950. cell s9_real_power(cell x, cell y) {
  1951. Tmp = x;
  1952. prot(y);
  1953. prot(x);
  1954. Tmp = NIL;
  1955. if (integer_p(y)) {
  1956. x = npower(x, y);
  1957. if (bignum_negative_p(y))
  1958. x = s9_real_divide(One, x);
  1959. unprot(2);
  1960. return x;
  1961. }
  1962. if (s9_real_negative_p(y)) {
  1963. y = s9_real_abs(y);
  1964. prot(y);
  1965. x = rpower(x, y, Epsilon);
  1966. unprot(3);
  1967. if (x == UNDEFINED)
  1968. return x;
  1969. return s9_real_divide(One, x);
  1970. }
  1971. x = rpower(x, y, Epsilon);
  1972. unprot(2);
  1973. return x;
  1974. }
  1975. /* type: 0=trunc, 1=floor, 2=ceil */
  1976. static cell rround(cell x, int type) {
  1977. cell n, m, e;
  1978. e = s9_real_exponent(x);
  1979. if (e >= 0)
  1980. return x;
  1981. prot(x);
  1982. m = new_atom(T_INTEGER, Real_mantissa(x));
  1983. prot(m);
  1984. while (e < 0) {
  1985. m = s9_bignum_shift_right(m);
  1986. m = car(m);
  1987. pref(0) = m;
  1988. e++;
  1989. }
  1990. if ( (type == 1 && Real_negative_p(x)) ||
  1991. (type == 2 && Real_positive_p(x))
  1992. ) {
  1993. m = s9_bignum_add(m, One);
  1994. }
  1995. n = S9_make_real(Real_flags(x), e, cdr(m));
  1996. unprot(2);
  1997. return n;
  1998. }
  1999. cell s9_real_trunc(cell x) { return rround(x, 0); }
  2000. cell s9_real_floor(cell x) { return rround(x, 1); }
  2001. cell s9_real_ceil (cell x) { return rround(x, 2); }
  2002. cell s9_real_to_bignum(cell r) {
  2003. cell n;
  2004. int neg;
  2005. if (Real_exponent(r) >= 0) {
  2006. prot(r);
  2007. neg = Real_negative_p(r);
  2008. n = scale_mantissa(r, 0, 0);
  2009. if (n == UNDEFINED) {
  2010. unprot(1);
  2011. return UNDEFINED;
  2012. }
  2013. n = new_atom(T_INTEGER, Real_mantissa(n));
  2014. if (neg)
  2015. n = s9_bignum_negate(n);
  2016. unprot(1);
  2017. return n;
  2018. }
  2019. return UNDEFINED;
  2020. }
  2021. cell s9_real_integer_p(cell x) {
  2022. if (integer_p(x))
  2023. return 1;
  2024. if (real_p(x) && s9_real_to_bignum(x) != UNDEFINED)
  2025. return 1;
  2026. return 0;
  2027. }
  2028. /*
  2029. * String/number conversion
  2030. */
  2031. static int exponent_char_p(int c) {
  2032. return c && strchr(Exponent_chars, c) != NULL;
  2033. }
  2034. int s9_integer_string_p(char *s) {
  2035. if (*s == '-' || *s == '+')
  2036. s++;
  2037. if (!*s)
  2038. return 0;
  2039. while (isdigit(*s))
  2040. s++;
  2041. return *s == 0;
  2042. }
  2043. int s9_string_numeric_p(char *s) {
  2044. int i;
  2045. int got_point = 0,
  2046. got_digit = 0;
  2047. i = 0;
  2048. if (s[0] == '+' || s[0] == '-')
  2049. i = 1;
  2050. if (!s[i])
  2051. return 0;
  2052. while (s[i]) {
  2053. if (isdigit(s[i])) {
  2054. got_digit = 1;
  2055. i++;
  2056. }
  2057. else if (s[i] == '.' && !got_point) {
  2058. got_point = 1;
  2059. i++;
  2060. }
  2061. else {
  2062. break;
  2063. }
  2064. }
  2065. if (!got_digit)
  2066. return 0;
  2067. if (s[i] && strchr(Exponent_chars, s[i]))
  2068. return s9_integer_string_p(&s[i+1]);
  2069. return s[i] == 0;
  2070. }
  2071. cell s9_string_to_bignum(char *s) {
  2072. cell n, v, str;
  2073. int k, j, sign;
  2074. sign = 1;
  2075. if (s[0] == '-') {
  2076. s++;
  2077. sign = -1;
  2078. }
  2079. else if (s[0] == '+') {
  2080. s++;
  2081. }
  2082. str = s9_make_string(s, strlen(s));
  2083. prot(str);
  2084. s = string(str);
  2085. k = (int) strlen(s);
  2086. n = NIL;
  2087. while (k) {
  2088. j = k <= S9_DIGITS_PER_CELL? k: S9_DIGITS_PER_CELL;
  2089. v = s9_asctol(&s[k-j]);
  2090. s[k-j] = 0;
  2091. k -= j;
  2092. n = new_atom(v, n);
  2093. s = string(str);
  2094. }
  2095. unprot(1);
  2096. car(n) = sign * car(n);
  2097. return new_atom(T_INTEGER, n);
  2098. }
  2099. cell s9_string_to_real(char *s) {
  2100. cell mantissa, n;
  2101. cell exponent;
  2102. int found_dp;
  2103. int neg = 0;
  2104. int i, j, v;
  2105. mantissa = Zero;
  2106. prot(mantissa);
  2107. exponent = 0;
  2108. i = 0;
  2109. if (s[i] == '+') {
  2110. i++;
  2111. }
  2112. else if (s[i] == '-') {
  2113. neg = 1;
  2114. i++;
  2115. }
  2116. found_dp = 0;
  2117. while (isdigit((int) s[i]) || s[i] == '#' || s[i] == '.') {
  2118. if (s[i] == '.') {
  2119. i++;
  2120. found_dp = 1;
  2121. continue;
  2122. }
  2123. if (found_dp)
  2124. exponent--;
  2125. mantissa = s9_bignum_shift_left(mantissa, 0);
  2126. pref(0) = mantissa;
  2127. if (s[i] == '#')
  2128. v = 5;
  2129. else
  2130. v = s[i]-'0';
  2131. mantissa = s9_bignum_add(mantissa, s9_make_integer(v));
  2132. pref(0) = mantissa;
  2133. i++;
  2134. }
  2135. j = 0;
  2136. for (n = cdr(mantissa); n != NIL; n = cdr(n))
  2137. j++;
  2138. if (exponent_char_p(s[i])) {
  2139. i++;
  2140. if (!isdigit(s[i]) && s[i] != '-' && s[i] != '+') {
  2141. unprot(1);
  2142. return UNDEFINED;
  2143. }
  2144. n = s9_string_to_bignum(&s[i]);
  2145. if (cddr(n) != NIL) {
  2146. unprot(1);
  2147. return UNDEFINED;
  2148. }
  2149. exponent += cadr(n);
  2150. }
  2151. unprot(1);
  2152. n = S9_make_quick_real((neg? REAL_NEGATIVE: 0),
  2153. exponent, cdr(mantissa));
  2154. return real_normalize(n);
  2155. }
  2156. cell s9_string_to_number(char *s) {
  2157. if (s9_integer_string_p(s))
  2158. return s9_string_to_bignum(s);
  2159. else
  2160. return s9_string_to_real(s);
  2161. }
  2162. void s9_print_bignum(cell n) {
  2163. int first;
  2164. char buf[S9_DIGITS_PER_CELL+2];
  2165. n = cdr(n);
  2166. first = 1;
  2167. while (n != NIL) {
  2168. s9_prints(ntoa(buf, car(n), first? 0: S9_DIGITS_PER_CELL));
  2169. n = cdr(n);
  2170. first = 0;
  2171. }
  2172. }
  2173. void s9_print_expanded_real(cell n) {
  2174. char buf[S9_DIGITS_PER_CELL+3];
  2175. int k, first;
  2176. int dp_offset, old_offset;
  2177. cell m, e;
  2178. int n_digits, neg;
  2179. m = Real_mantissa(n);
  2180. e = Real_exponent(n);
  2181. neg = Real_negative_p(n);
  2182. n_digits = count_digits(m);
  2183. dp_offset = e+n_digits;
  2184. if (neg)
  2185. s9_prints("-");
  2186. if (dp_offset <= 0)
  2187. s9_prints("0");
  2188. if (dp_offset < 0)
  2189. s9_prints(".");
  2190. while (dp_offset < 0) {
  2191. s9_prints("0");
  2192. dp_offset++;
  2193. }
  2194. dp_offset = e+n_digits;
  2195. first = 1;
  2196. while (m != NIL) {
  2197. ntoa(buf, labs(car(m)), first? 0: S9_DIGITS_PER_CELL);
  2198. k = strlen(buf);
  2199. old_offset = dp_offset;
  2200. dp_offset -= k;
  2201. if (dp_offset < 0 && old_offset >= 0) {
  2202. memmove(&buf[k+dp_offset+1], &buf[k+dp_offset],
  2203. -dp_offset+1);
  2204. buf[k+dp_offset] = '.';
  2205. }
  2206. s9_prints(buf);
  2207. m = cdr(m);
  2208. first = 0;
  2209. }
  2210. if (dp_offset >= 0) {
  2211. while (dp_offset > 0) {
  2212. s9_prints("0");
  2213. dp_offset--;
  2214. }
  2215. s9_prints(".0");
  2216. }
  2217. }
  2218. void s9_print_sci_real(cell n) {
  2219. int n_digits;
  2220. cell m, e;
  2221. char buf[S9_DIGITS_PER_CELL+2];
  2222. char es[2];
  2223. m = Real_mantissa(n);
  2224. e = Real_exponent(n);
  2225. n_digits = count_digits(m);
  2226. if (Real_negative_flag(n))
  2227. s9_prints("-");
  2228. ntoa(buf, car(m), 0);
  2229. s9_blockwrite(buf, 1);
  2230. s9_prints(".");
  2231. s9_prints(buf[1] || cdr(m) != NIL? &buf[1]: "0");
  2232. m = cdr(m);
  2233. while (m != NIL) {
  2234. s9_prints(ntoa(buf, car(m), S9_DIGITS_PER_CELL));
  2235. m = cdr(m);
  2236. }
  2237. es[0] = Exponent_chars[0];
  2238. es[1] = 0;
  2239. s9_prints(es);
  2240. if (e+n_digits-1 >= 0)
  2241. s9_prints("+");
  2242. s9_prints(ntoa(buf, e+n_digits-1, 0));
  2243. }
  2244. void s9_print_real(cell n) {
  2245. int n_digits;
  2246. cell m, e;
  2247. m = Real_mantissa(n);
  2248. e = Real_exponent(n);
  2249. n_digits = count_digits(m);
  2250. if (e+n_digits > -S9_MANTISSA_SIZE && e+n_digits <= S9_MANTISSA_SIZE) {
  2251. s9_print_expanded_real(n);
  2252. return;
  2253. }
  2254. s9_print_sci_real(n);
  2255. }
  2256. cell s9_bignum_to_int(cell x, int *of) {
  2257. int a, b, s;
  2258. *of = 0;
  2259. if (small_int_p(x)) return small_int_value(x);
  2260. if (NIL == cdddr(x)) {
  2261. if ((size_t) S9_INT_SEG_LIMIT > (size_t) INT_MAX)
  2262. s9_fatal("bignum_to_int(): multi-segment integers "
  2263. "unsupported in 64-bit mode");
  2264. a = cadr(x);
  2265. b = caddr(x);
  2266. if (a > INT_MAX / S9_INT_SEG_LIMIT) {
  2267. *of = 1;
  2268. return 0;
  2269. }
  2270. if (a < INT_MIN / S9_INT_SEG_LIMIT) {
  2271. *of = 1;
  2272. return 0;
  2273. }
  2274. s = a<0? -1: 1;
  2275. a = abs(a) * S9_INT_SEG_LIMIT;
  2276. if (b > INT_MAX - a) {
  2277. *of = 1;
  2278. return 0;
  2279. }
  2280. return s*(a+b);
  2281. }
  2282. *of = 1;
  2283. return 0;
  2284. }
  2285. cell s9_int_to_bignum(int v) {
  2286. cell n;
  2287. if (v >= 0 && (long) v < S9_INT_SEG_LIMIT)
  2288. return s9_make_integer(v);
  2289. if (v < 0 && (long) -v < S9_INT_SEG_LIMIT)
  2290. return s9_make_integer(v);
  2291. if ((size_t) S9_INT_SEG_LIMIT > (size_t) INT_MAX)
  2292. s9_fatal("int_to_bignum(): multi-segment integers "
  2293. "unsupported in 64-bit mode");
  2294. n = new_atom(abs(v) % S9_INT_SEG_LIMIT, NIL);
  2295. n = new_atom(v / S9_INT_SEG_LIMIT, n);
  2296. return new_atom(T_INTEGER, n);
  2297. }
  2298. cell s9_bignum_to_string(cell x) {
  2299. int n;
  2300. cell s;
  2301. int ioe;
  2302. prot(x);
  2303. n = count_digits(cdr(x));
  2304. if (bignum_negative_p(x))
  2305. n++;
  2306. s = s9_make_string("", n);
  2307. Str_outport = string(s);
  2308. Str_outport_len = n+1;
  2309. ioe = IO_error;
  2310. IO_error = 0;
  2311. s9_print_bignum(x);
  2312. n = IO_error;
  2313. IO_error = ioe;
  2314. Str_outport = NULL;
  2315. Str_outport_len = 0;
  2316. unprot(1);
  2317. if (n) {
  2318. return UNDEFINED;
  2319. }
  2320. return s;
  2321. }
  2322. cell s9_real_to_string(cell x, int mode) {
  2323. #define Z S9_MANTISSA_SIZE+S9_DIGITS_PER_CELL+10
  2324. char buf[Z];
  2325. int ioe, n;
  2326. Str_outport = buf;
  2327. Str_outport_len = Z;
  2328. ioe = IO_error;
  2329. IO_error = 0;
  2330. switch (mode) {
  2331. case 0: s9_print_real(x); break;
  2332. case 1: s9_print_sci_real(x); break;
  2333. case 2: s9_print_expanded_real(x); break;
  2334. default:
  2335. Str_outport = NULL;
  2336. Str_outport_len = 0;
  2337. return UNDEFINED;
  2338. break;
  2339. }
  2340. Str_outport = NULL;
  2341. Str_outport_len = 0;
  2342. n = IO_error;
  2343. IO_error = ioe;
  2344. if (n) {
  2345. return UNDEFINED;
  2346. }
  2347. return s9_make_string(buf, strlen(buf));
  2348. }
  2349. /*
  2350. * I/O
  2351. */
  2352. void s9_close_port(int port) {
  2353. if (port < 0 || port >= S9_MAX_PORTS)
  2354. return;
  2355. if (Ports[port] == NULL) {
  2356. Port_flags[port] = 0;
  2357. return;
  2358. }
  2359. fclose(Ports[port]); /* already closed? don't care */
  2360. Ports[port] = NULL;
  2361. Port_flags[port] = 0;
  2362. }
  2363. int s9_new_port(void) {
  2364. int i, tries;
  2365. for (tries=0; tries<2; tries++) {
  2366. for (i=0; i<S9_MAX_PORTS; i++) {
  2367. if (Ports[i] == NULL)
  2368. return i;
  2369. }
  2370. if (tries == 0)
  2371. s9_gc();
  2372. }
  2373. return -1;
  2374. }
  2375. int s9_open_input_port(char *path) {
  2376. int i = s9_new_port();
  2377. if (i < 0)
  2378. return -1;
  2379. Ports[i] = fopen(path, "r");
  2380. if (Ports[i] == NULL)
  2381. return -1;
  2382. return i;
  2383. }
  2384. int s9_open_output_port(char *path, int append) {
  2385. int i = s9_new_port();
  2386. if (i < 0)
  2387. return -1;
  2388. Ports[i] = fopen(path, append? "a": "w");
  2389. if (Ports[i] == NULL)
  2390. return -1;
  2391. return i;
  2392. }
  2393. int s9_port_eof(int p) {
  2394. if (p < 0 || p >= S9_MAX_PORTS)
  2395. return -1;
  2396. return feof(Ports[p]);
  2397. }
  2398. int s9_error_port(void) {
  2399. return Error_port;
  2400. }
  2401. int s9_input_port(void) {
  2402. return Str_inport? -1: Input_port;
  2403. }
  2404. int s9_output_port(void) {
  2405. return Output_port;
  2406. }
  2407. cell s9_set_input_port(cell port) {
  2408. cell p = Input_port;
  2409. Input_port = port;
  2410. return p;
  2411. }
  2412. cell s9_set_output_port(cell port) {
  2413. cell p = Output_port;
  2414. Output_port = port;
  2415. return p;
  2416. }
  2417. void s9_reset_std_ports(void) {
  2418. clearerr(stdin);
  2419. clearerr(stdout);
  2420. clearerr(stderr);
  2421. Input_port = 0;
  2422. Output_port = 1;
  2423. Error_port

Large files files are truncated, but you can click here to view the full file