home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / unix / volume26 / calc / part12 < prev    next >
Encoding:
Text File  |  1992-05-09  |  30.0 KB  |  1,382 lines

  1. Newsgroups: comp.sources.unix
  2. From: dbell@pdact.pd.necisa.oz.au (David I. Bell)
  3. Subject: v26i038: CALC - An arbitrary precision C-like calculator, Part12/21
  4. Sender: unix-sources-moderator@pa.dec.com
  5. Approved: vixie@pa.dec.com
  6.  
  7. Submitted-By: dbell@pdact.pd.necisa.oz.au (David I. Bell)
  8. Posting-Number: Volume 26, Issue 38
  9. Archive-Name: calc/part12
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 12 (of 21)."
  18. # Contents:  value.c
  19. # Wrapped by dbell@elm on Tue Feb 25 15:21:10 1992
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'value.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'value.c'\"
  23. else
  24. echo shar: Extracting \"'value.c'\" \(27747 characters\)
  25. sed "s/^X//" >'value.c' <<'END_OF_FILE'
  26. X/*
  27. X * Copyright (c) 1992 David I. Bell
  28. X * Permission is granted to use, distribute, or modify this source,
  29. X * provided that this copyright notice remains intact.
  30. X *
  31. X * Generic value manipulation routines.
  32. X */
  33. X
  34. X#include "calc.h"
  35. X#include "opcodes.h"
  36. X#include "func.h"
  37. X#include "symbol.h"
  38. X
  39. X
  40. X/*
  41. X * Free a value and set its type to undefined.
  42. X */
  43. Xvoid
  44. Xfreevalue(vp)
  45. X    register VALUE *vp;    /* value to be freed */
  46. X{
  47. X    int type;        /* type of value being freed */
  48. X
  49. X    type = vp->v_type;
  50. X    vp->v_type = V_NULL;
  51. X    switch (type) {
  52. X        case V_NULL:
  53. X        case V_ADDR:
  54. X        case V_FILE:
  55. X            break;
  56. X        case V_STR:
  57. X            if (vp->v_subtype == V_STRALLOC)
  58. X                free(vp->v_str);
  59. X            break;
  60. X        case V_NUM:
  61. X            qfree(vp->v_num);
  62. X            break;
  63. X        case V_COM:
  64. X            comfree(vp->v_com);
  65. X            break;
  66. X        case V_MAT:
  67. X            matfree(vp->v_mat);
  68. X            break;
  69. X        case V_LIST:
  70. X            listfree(vp->v_list);
  71. X            break;
  72. X        case V_OBJ:
  73. X            objfree(vp->v_obj);
  74. X            break;
  75. X        default:
  76. X            error("Freeing unknown value type");
  77. X    }
  78. X}
  79. X
  80. X
  81. X/*
  82. X * Copy a value from one location to another.
  83. X * This overwrites the specified new value without checking it.
  84. X */
  85. Xvoid
  86. Xcopyvalue(oldvp, newvp)
  87. X    register VALUE *oldvp;        /* value to be copied from */
  88. X    register VALUE *newvp;        /* value to be copied into */
  89. X{
  90. X    newvp->v_type = V_NULL;
  91. X    switch (oldvp->v_type) {
  92. X        case V_NULL:
  93. X            break;
  94. X        case V_FILE:
  95. X            newvp->v_file = oldvp->v_file;
  96. X            break;
  97. X        case V_NUM:
  98. X            newvp->v_num = qlink(oldvp->v_num);
  99. X            break;
  100. X        case V_COM:
  101. X            newvp->v_com = clink(oldvp->v_com);
  102. X            break;
  103. X        case V_STR:
  104. X            newvp->v_str = oldvp->v_str;
  105. X            if (oldvp->v_subtype == V_STRALLOC) {
  106. X                newvp->v_str = (char *)malloc(strlen(oldvp->v_str) + 1);
  107. X                if (newvp->v_str == NULL)
  108. X                    error("Cannot get memory for string copy");
  109. X                strcpy(newvp->v_str, oldvp->v_str);
  110. X            }
  111. X            break;
  112. X        case V_MAT:
  113. X            newvp->v_mat = matcopy(oldvp->v_mat);
  114. X            break;
  115. X        case V_LIST:
  116. X            newvp->v_list = listcopy(oldvp->v_list);
  117. X            break;
  118. X        case V_ADDR:
  119. X            newvp->v_addr = oldvp->v_addr;
  120. X            break;
  121. X        case V_OBJ:
  122. X            newvp->v_obj = objcopy(oldvp->v_obj);
  123. X            break;
  124. X        default:
  125. X            error("Copying unknown value type");
  126. X    }
  127. X    newvp->v_subtype = oldvp->v_subtype;
  128. X    newvp->v_type = oldvp->v_type;
  129. X
  130. X}
  131. X
  132. X
  133. X/*
  134. X * Negate an arbitrary value.
  135. X * Result is placed in the indicated location.
  136. X */
  137. Xvoid
  138. Xnegvalue(vp, vres)
  139. X    VALUE *vp, *vres;
  140. X{
  141. X    vres->v_type = V_NULL;
  142. X    switch (vp->v_type) {
  143. X        case V_NUM:
  144. X            vres->v_num = qneg(vp->v_num);
  145. X            vres->v_type = V_NUM;
  146. X            return;
  147. X        case V_COM:
  148. X            vres->v_com = cneg(vp->v_com);
  149. X            vres->v_type = V_COM;
  150. X            return;
  151. X        case V_MAT:
  152. X            vres->v_mat = matneg(vp->v_mat);
  153. X            vres->v_type = V_MAT;
  154. X            return;
  155. X        case V_OBJ:
  156. X            *vres = objcall(OBJ_NEG, vp);
  157. X            return;
  158. X        default:
  159. X            error("Illegal value for negation");
  160. X    }
  161. X}
  162. X
  163. X
  164. X/*
  165. X * Add two arbitrary values together.
  166. X * Result is placed in the indicated location.
  167. X */
  168. Xvoid
  169. Xaddvalue(v1, v2, vres)
  170. X    VALUE *v1, *v2, *vres;
  171. X{
  172. X    COMPLEX *c;
  173. X
  174. X    vres->v_type = V_NULL;
  175. X    switch (TWOVAL(v1->v_type, v2->v_type)) {
  176. X        case TWOVAL(V_NUM, V_NUM):
  177. X            vres->v_num = qadd(v1->v_num, v2->v_num);
  178. X            vres->v_type = V_NUM;
  179. X            return;
  180. X        case TWOVAL(V_COM, V_NUM):
  181. X            vres->v_com = caddq(v1->v_com, v2->v_num);
  182. X            vres->v_type = V_COM;
  183. X            return;
  184. X        case TWOVAL(V_NUM, V_COM):
  185. X            vres->v_com = caddq(v2->v_com, v1->v_num);
  186. X            vres->v_type = V_COM;
  187. X            return;
  188. X        case TWOVAL(V_COM, V_COM):
  189. X            vres->v_com = cadd(v1->v_com, v2->v_com);
  190. X            vres->v_type = V_COM;
  191. X            c = vres->v_com;
  192. X            if (!cisreal(c))
  193. X                return;
  194. X            vres->v_num = qlink(c->real);
  195. X            vres->v_type = V_NUM;
  196. X            comfree(c);
  197. X            return;
  198. X        case TWOVAL(V_MAT, V_MAT):
  199. X            vres->v_mat = matadd(v1->v_mat, v2->v_mat);
  200. X            vres->v_type = V_MAT;
  201. X            return;
  202. X        default:
  203. X            if ((v1->v_type != V_OBJ) && (v2->v_type != V_OBJ))
  204. X                error("Non-compatible values for add");
  205. X            *vres = objcall(OBJ_ADD, v1, v2);
  206. X            return;
  207. X    }
  208. X}
  209. X
  210. X
  211. X/*
  212. X * Subtract one arbitrary value from another one.
  213. X * Result is placed in the indicated location.
  214. X */
  215. Xvoid
  216. Xsubvalue(v1, v2, vres)
  217. X    VALUE *v1, *v2, *vres;
  218. X{
  219. X    COMPLEX *c;
  220. X
  221. X    vres->v_type = V_NULL;
  222. X    switch (TWOVAL(v1->v_type, v2->v_type)) {
  223. X        case TWOVAL(V_NUM, V_NUM):
  224. X            vres->v_num = qsub(v1->v_num, v2->v_num);
  225. X            vres->v_type = V_NUM;
  226. X            return;
  227. X        case TWOVAL(V_COM, V_NUM):
  228. X            vres->v_com = csubq(v1->v_com, v2->v_num);
  229. X            vres->v_type = V_COM;
  230. X            return;
  231. X        case TWOVAL(V_NUM, V_COM):
  232. X            c = csubq(v2->v_com, v1->v_num);
  233. X            vres->v_com = cneg(c);
  234. X            comfree(c);
  235. X            vres->v_type = V_COM;
  236. X            return;
  237. X        case TWOVAL(V_COM, V_COM):
  238. X            vres->v_com = csub(v1->v_com, v2->v_com);
  239. X            vres->v_type = V_COM;
  240. X            c = vres->v_com;
  241. X            if (!cisreal(c))
  242. X                return;
  243. X            vres->v_num = qlink(c->real);
  244. X            vres->v_type = V_NUM;
  245. X            comfree(c);
  246. X            return;
  247. X        case TWOVAL(V_MAT, V_MAT):
  248. X            vres->v_mat = matsub(v1->v_mat, v2->v_mat);
  249. X            vres->v_type = V_MAT;
  250. X            return;
  251. X        default:
  252. X            if ((v1->v_type != V_OBJ) && (v2->v_type != V_OBJ))
  253. X                error("Non-compatible values for subtract");
  254. X            *vres = objcall(OBJ_SUB, v1, v2);
  255. X            return;
  256. X    }
  257. X}
  258. X
  259. X
  260. X/*
  261. X * Multiply two arbitrary values together.
  262. X * Result is placed in the indicated location.
  263. X */
  264. Xvoid
  265. Xmulvalue(v1, v2, vres)
  266. X    VALUE *v1, *v2, *vres;
  267. X{
  268. X    COMPLEX *c;
  269. X
  270. X    vres->v_type = V_NULL;
  271. X    switch (TWOVAL(v1->v_type, v2->v_type)) {
  272. X        case TWOVAL(V_NUM, V_NUM):
  273. X            vres->v_num = qmul(v1->v_num, v2->v_num);
  274. X            vres->v_type = V_NUM;
  275. X            return;
  276. X        case TWOVAL(V_COM, V_NUM):
  277. X            vres->v_com = cmulq(v1->v_com, v2->v_num);
  278. X            vres->v_type = V_COM;
  279. X            break;
  280. X        case TWOVAL(V_NUM, V_COM):
  281. X            vres->v_com = cmulq(v2->v_com, v1->v_num);
  282. X            vres->v_type = V_COM;
  283. X            break;
  284. X        case TWOVAL(V_COM, V_COM):
  285. X            vres->v_com = cmul(v1->v_com, v2->v_com);
  286. X            vres->v_type = V_COM;
  287. X            break;
  288. X        case TWOVAL(V_MAT, V_MAT):
  289. X            vres->v_mat = matmul(v1->v_mat, v2->v_mat);
  290. X            vres->v_type = V_MAT;
  291. X            return;
  292. X        case TWOVAL(V_MAT, V_NUM):
  293. X        case TWOVAL(V_MAT, V_COM):
  294. X            vres->v_mat = matmulval(v1->v_mat, v2);
  295. X            vres->v_type = V_MAT;
  296. X            return;
  297. X        case TWOVAL(V_NUM, V_MAT):
  298. X        case TWOVAL(V_COM, V_MAT):
  299. X            vres->v_mat = matmulval(v2->v_mat, v1);
  300. X            vres->v_type = V_MAT;
  301. X            return;
  302. X        default:
  303. X            if ((v1->v_type != V_OBJ) && (v2->v_type != V_OBJ))
  304. X                error("Non-compatible values for multiply");
  305. X            *vres = objcall(OBJ_MUL, v1, v2);
  306. X            return;
  307. X    }
  308. X    c = vres->v_com;
  309. X    if (cisreal(c)) {
  310. X        vres->v_num = qlink(c->real);
  311. X        vres->v_type = V_NUM;
  312. X        comfree(c);
  313. X    }
  314. X}
  315. X
  316. X
  317. X/*
  318. X * Square an arbitrary value.
  319. X * Result is placed in the indicated location.
  320. X */
  321. Xvoid
  322. Xsquarevalue(vp, vres)
  323. X    VALUE *vp, *vres;
  324. X{
  325. X    COMPLEX *c;
  326. X
  327. X    vres->v_type = V_NULL;
  328. X    switch (vp->v_type) {
  329. X        case V_NUM:
  330. X            vres->v_num = qsquare(vp->v_num);
  331. X            vres->v_type = V_NUM;
  332. X            return;
  333. X        case V_COM:
  334. X            vres->v_com = csquare(vp->v_com);
  335. X            vres->v_type = V_COM;
  336. X            c = vres->v_com;
  337. X            if (!cisreal(c))
  338. X                return;
  339. X            vres->v_num = qlink(c->real);
  340. X            vres->v_type = V_NUM;
  341. X            comfree(c);
  342. X            return;
  343. X        case V_MAT:
  344. X            vres->v_mat = matsquare(vp->v_mat);
  345. X            vres->v_type = V_MAT;
  346. X            return;
  347. X        case V_OBJ:
  348. X            *vres = objcall(OBJ_SQUARE, vp);
  349. X            return;
  350. X        default:
  351. X            error("Illegal value for squaring");
  352. X    }
  353. X}
  354. X
  355. X
  356. X/*
  357. X * Invert an arbitrary value.
  358. X * Result is placed in the indicated location.
  359. X */
  360. Xvoid
  361. Xinvertvalue(vp, vres)
  362. X    VALUE *vp, *vres;
  363. X{
  364. X    vres->v_type = V_NULL;
  365. X    switch (vp->v_type) {
  366. X        case V_NUM:
  367. X            vres->v_num = qinv(vp->v_num);
  368. X            vres->v_type = V_NUM;
  369. X            return;
  370. X        case V_COM:
  371. X            vres->v_com = cinv(vp->v_com);
  372. X            vres->v_type = V_COM;
  373. X            return;
  374. X        case V_MAT:
  375. X            vres->v_mat = matinv(vp->v_mat);
  376. X            vres->v_type = V_MAT;
  377. X            return;
  378. X        case V_OBJ:
  379. X            *vres = objcall(OBJ_INV, vp);
  380. X            return;
  381. X        default:
  382. X            error("Illegal value for inverting");
  383. X    }
  384. X}
  385. X
  386. X
  387. X/*
  388. X * Round an arbitrary value to the specified number of decimal places.
  389. X * Result is placed in the indicated location.
  390. X */
  391. Xvoid
  392. Xroundvalue(v1, v2, vres)
  393. X    VALUE *v1, *v2, *vres;
  394. X{
  395. X    long places;
  396. X    NUMBER *q;
  397. X    COMPLEX *c;
  398. X
  399. X    switch (v2->v_type) {
  400. X        case V_NUM:
  401. X            q = v2->v_num;
  402. X            if (qisfrac(q) || isbig(q->num))
  403. X                error("Bad number of places for round");
  404. X            places = qtoi(q);
  405. X            break;
  406. X        case V_INT:
  407. X            places = v2->v_int;
  408. X            break;
  409. X        default:
  410. X            error("Bad value type for places in round");
  411. X    }
  412. X    if (places < 0)
  413. X        error("Negative number of places in round");
  414. X    vres->v_type = V_NULL;
  415. X    switch (v1->v_type) {
  416. X        case V_NUM:
  417. X            if (qisint(v1->v_num))
  418. X                vres->v_num = qlink(v1->v_num);
  419. X            else
  420. X                vres->v_num = qround(v1->v_num, places);
  421. X            vres->v_type = V_NUM;
  422. X            return;
  423. X        case V_COM:
  424. X            if (cisint(v1->v_com)) {
  425. X                vres->v_com = clink(v1->v_com);
  426. X                vres->v_type = V_COM;
  427. X                return;
  428. X            }
  429. X            vres->v_com = cround(v1->v_com, places);
  430. X            vres->v_type = V_COM;
  431. X            c = vres->v_com;
  432. X            if (cisreal(c)) {
  433. X                vres->v_num = qlink(c->real);
  434. X                vres->v_type = V_NUM;
  435. X                comfree(c);
  436. X            }
  437. X            return;
  438. X        case V_MAT:
  439. X            vres->v_mat = matround(v1->v_mat, places);
  440. X            vres->v_type = V_MAT;
  441. X            return;
  442. X        case V_OBJ:
  443. X            *vres = objcall(OBJ_ROUND, v1, v2);
  444. X            return;
  445. X        default:
  446. X            error("Illegal value for round");
  447. X    }
  448. X}
  449. X
  450. X
  451. X/*
  452. X * Round an arbitrary value to the specified number of binary places.
  453. X * Result is placed in the indicated location.
  454. X */
  455. Xvoid
  456. Xbroundvalue(v1, v2, vres)
  457. X    VALUE *v1, *v2, *vres;
  458. X{
  459. X    long places;
  460. X    NUMBER *q;
  461. X    COMPLEX *c;
  462. X
  463. X    switch (v2->v_type) {
  464. X        case V_NUM:
  465. X            q = v2->v_num;
  466. X            if (qisfrac(q) || isbig(q->num))
  467. X                error("Bad number of places for bround");
  468. X            places = qtoi(q);
  469. X            break;
  470. X        case V_INT:
  471. X            places = v2->v_int;
  472. X            break;
  473. X        default:
  474. X            error("Bad value type for places in bround");
  475. X    }
  476. X    if (places < 0)
  477. X        error("Negative number of places in bround");
  478. X    vres->v_type = V_NULL;
  479. X    switch (v1->v_type) {
  480. X        case V_NUM:
  481. X            if (qisint(v1->v_num))
  482. X                vres->v_num = qlink(v1->v_num);
  483. X            else
  484. X                vres->v_num = qbround(v1->v_num, places);
  485. X            vres->v_type = V_NUM;
  486. X            return;
  487. X        case V_COM:
  488. X            if (cisint(v1->v_com)) {
  489. X                vres->v_com = clink(v1->v_com);
  490. X                vres->v_type = V_COM;
  491. X                return;
  492. X            }
  493. X            vres->v_com = cbround(v1->v_com, places);
  494. X            vres->v_type = V_COM;
  495. X            c = vres->v_com;
  496. X            if (cisreal(c)) {
  497. X                vres->v_num = qlink(c->real);
  498. X                vres->v_type = V_NUM;
  499. X                comfree(c);
  500. X            }
  501. X            return;
  502. X        case V_MAT:
  503. X            vres->v_mat = matbround(v1->v_mat, places);
  504. X            vres->v_type = V_MAT;
  505. X            return;
  506. X        case V_OBJ:
  507. X            *vres = objcall(OBJ_BROUND, v1, v2);
  508. X            return;
  509. X        default:
  510. X            error("Illegal value for bround");
  511. X    }
  512. X}
  513. X
  514. X
  515. X/*
  516. X * Take the integer part of an arbitrary value.
  517. X * Result is placed in the indicated location.
  518. X */
  519. Xvoid
  520. Xintvalue(vp, vres)
  521. X    VALUE *vp, *vres;
  522. X{
  523. X    COMPLEX *c;
  524. X
  525. X    vres->v_type = V_NULL;
  526. X    switch (vp->v_type) {
  527. X        case V_NUM:
  528. X            if (qisint(vp->v_num))
  529. X                vres->v_num = qlink(vp->v_num);
  530. X            else
  531. X                vres->v_num = qint(vp->v_num);
  532. X            vres->v_type = V_NUM;
  533. X            return;
  534. X        case V_COM:
  535. X            if (cisint(vp->v_com)) {
  536. X                vres->v_com = clink(vp->v_com);
  537. X                vres->v_type = V_COM;
  538. X                return;
  539. X            }
  540. X            vres->v_com = cint(vp->v_com);
  541. X            vres->v_type = V_COM;
  542. X            c = vres->v_com;
  543. X            if (cisreal(c)) {
  544. X                vres->v_num = qlink(c->real);
  545. X                vres->v_type = V_NUM;
  546. X                comfree(c);
  547. X            }
  548. X            return;
  549. X        case V_MAT:
  550. X            vres->v_mat = matint(vp->v_mat);
  551. X            vres->v_type = V_MAT;
  552. X            return;
  553. X        case V_OBJ:
  554. X            *vres = objcall(OBJ_INT, vp);
  555. X            return;
  556. X        default:
  557. X            error("Illegal value for int");
  558. X    }
  559. X}
  560. X
  561. X
  562. X/*
  563. X * Take the fractional part of an arbitrary value.
  564. X * Result is placed in the indicated location.
  565. X */
  566. Xvoid
  567. Xfracvalue(vp, vres)
  568. X    VALUE *vp, *vres;
  569. X{
  570. X    vres->v_type = V_NULL;
  571. X    switch (vp->v_type) {
  572. X        case V_NUM:
  573. X            if (qisint(vp->v_num))
  574. X                vres->v_num = qlink(&_qzero_);
  575. X            else
  576. X                vres->v_num = qfrac(vp->v_num);
  577. X            vres->v_type = V_NUM;
  578. X            return;
  579. X        case V_COM:
  580. X            if (cisint(vp->v_com)) {
  581. X                vres->v_num = clink(&_qzero_);
  582. X                vres->v_type = V_NUM;
  583. X                return;
  584. X            }
  585. X            vres->v_com = cfrac(vp->v_com);
  586. X            vres->v_type = V_COM;
  587. X            return;
  588. X        case V_MAT:
  589. X            vres->v_mat = matfrac(vp->v_mat);
  590. X            vres->v_type = V_MAT;
  591. X            return;
  592. X        case V_OBJ:
  593. X            *vres = objcall(OBJ_FRAC, vp);
  594. X            return;
  595. X        default:
  596. X            error("Illegal value for frac function");
  597. X    }
  598. X}
  599. X
  600. X
  601. X/*
  602. X * Increment an arbitrary value by one.
  603. X * Result is placed in the indicated location.
  604. X */
  605. Xvoid
  606. Xincvalue(vp, vres)
  607. X    VALUE *vp, *vres;
  608. X{
  609. X    switch (vp->v_type) {
  610. X        case V_NUM:
  611. X            vres->v_num = qinc(vp->v_num);
  612. X            vres->v_type = V_NUM;
  613. X            return;
  614. X        case V_COM:
  615. X            vres->v_com = caddq(vp->v_com, &_qone_);
  616. X            vres->v_type = V_COM;
  617. X            return;
  618. X        case V_OBJ:
  619. X            *vres = objcall(OBJ_INC, vp);
  620. X            return;
  621. X        default:
  622. X            error("Illegal value for incrementing");
  623. X    }
  624. X}
  625. X
  626. X
  627. X/*
  628. X * Decrement an arbitrary value by one.
  629. X * Result is placed in the indicated location.
  630. X */
  631. Xvoid
  632. Xdecvalue(vp, vres)
  633. X    VALUE *vp, *vres;
  634. X{
  635. X    switch (vp->v_type) {
  636. X        case V_NUM:
  637. X            vres->v_num = qdec(vp->v_num);
  638. X            vres->v_type = V_NUM;
  639. X            return;
  640. X        case V_COM:
  641. X            vres->v_com = caddq(vp->v_com, &_qnegone_);
  642. X            vres->v_type = V_COM;
  643. X            return;
  644. X        case V_OBJ:
  645. X            *vres = objcall(OBJ_DEC, vp);
  646. X            return;
  647. X        default:
  648. X            error("Illegal value for decrementing");
  649. X    }
  650. X}
  651. X
  652. X
  653. X/*
  654. X * Produce the 'conjugate' of an arbitrary value.
  655. X * Result is placed in the indicated location.
  656. X * (Example: complex conjugate.)
  657. X */
  658. Xvoid
  659. Xconjvalue(vp, vres)
  660. X    VALUE *vp, *vres;
  661. X{
  662. X    vres->v_type = V_NULL;
  663. X    switch (vp->v_type) {
  664. X        case V_NUM:
  665. X            vres->v_num = qlink(vp->v_num);
  666. X            vres->v_type = V_NUM;
  667. X            return;
  668. X        case V_COM:
  669. X            vres->v_com = comalloc();
  670. X            vres->v_com->real = qlink(vp->v_com->real);
  671. X            vres->v_com->imag = qneg(vp->v_com->imag);
  672. X            vres->v_type = V_COM;
  673. X            return;
  674. X        case V_MAT:
  675. X            vres->v_mat = matconj(vp->v_mat);
  676. X            vres->v_type = V_MAT;
  677. X            return;
  678. X        case V_OBJ:
  679. X            *vres = objcall(OBJ_CONJ, vp);
  680. X            return;
  681. X        default:
  682. X            error("Illegal value for conjugation");
  683. X    }
  684. X}
  685. X
  686. X
  687. X/*
  688. X * Take the square root of an arbitrary value within the specified error.
  689. X * Result is placed in the indicated location.
  690. X */
  691. Xvoid
  692. Xsqrtvalue(v1, v2, vres)
  693. X    VALUE *v1, *v2, *vres;
  694. X{
  695. X    NUMBER *q, *tmp;
  696. X    COMPLEX *c;
  697. X
  698. X    if (v2->v_type != V_NUM)
  699. X        error("Non-real epsilon for sqrt");
  700. X    q = v2->v_num;
  701. X    if (qisneg(q) || qiszero(q))
  702. X        error("Illegal epsilon value for sqrt");
  703. X    switch (v1->v_type) {
  704. X        case V_NUM:
  705. X            if (!qisneg(v1->v_num)) {
  706. X                vres->v_num = qsqrt(v1->v_num, q);
  707. X                vres->v_type = V_NUM;
  708. X                return;
  709. X            }
  710. X            tmp = qneg(v1->v_num);
  711. X            c = comalloc();
  712. X            c->imag = qsqrt(tmp, q);
  713. X            qfree(tmp);
  714. X            vres->v_com = c;
  715. X            vres->v_type = V_COM;
  716. X            return;
  717. X        case V_COM:
  718. X            vres->v_com = csqrt(v1->v_com, q);
  719. X            vres->v_type = V_COM;
  720. X            return;
  721. X        case V_OBJ:
  722. X            *vres = objcall(OBJ_SQRT, v1, v2);
  723. X            return;
  724. X        default:
  725. X            error("Bad value for taking square root");
  726. X    }
  727. X}
  728. X
  729. X
  730. X/*
  731. X * Take the Nth root of an arbitrary value within the specified error.
  732. X * Result is placed in the indicated location.
  733. X */
  734. Xvoid
  735. Xrootvalue(v1, v2, v3, vres)
  736. X    VALUE *v1;        /* value to take root of */
  737. X    VALUE *v2;        /* value specifying root to take */
  738. X    VALUE *v3;        /* value specifying error */
  739. X    VALUE *vres;
  740. X{
  741. X    NUMBER *q1, *q2;
  742. X    COMPLEX ctmp;
  743. X
  744. X    if ((v2->v_type != V_NUM) || (v3->v_type != V_NUM))
  745. X        error("Non-real arguments for root");
  746. X    q1 = v2->v_num;
  747. X    q2 = v3->v_num;
  748. X    if (qisneg(q1) || qiszero(q1) || qisfrac(q1))
  749. X        error("Non-positive or non-integral root");
  750. X    if (qisneg(q2) || qiszero(q2))
  751. X        error("Non-positive epsilon for root");
  752. X    switch (v1->v_type) {
  753. X        case V_NUM:
  754. X            if (!qisneg(v1->v_num) || isodd(q1->num)) {
  755. X                vres->v_num = qroot(v1->v_num, q1, q2);
  756. X                vres->v_type = V_NUM;
  757. X                return;
  758. X            }
  759. X            ctmp.real = v1->v_num;
  760. X            ctmp.imag = &_qzero_;
  761. X            vres->v_com = croot(&ctmp, q1, q2);
  762. X            vres->v_type = V_COM;
  763. X            return;
  764. X        case V_COM:
  765. X            vres->v_com = croot(v1->v_com, q1, q2);
  766. X            vres->v_type = V_COM;
  767. X            return;
  768. X        case V_OBJ:
  769. X            *vres = objcall(OBJ_ROOT, v1, v2, v3);
  770. X            return;
  771. X        default:
  772. X            error("Taking root of bad value");
  773. X    }
  774. X}
  775. X
  776. X
  777. X/*
  778. X * Take the absolute value of an arbitrary value within the specified error.
  779. X * Result is placed in the indicated location.
  780. X */
  781. Xvoid
  782. Xabsvalue(v1, v2, vres)
  783. X    VALUE *v1, *v2, *vres;
  784. X{
  785. X    NUMBER *q, *epsilon;
  786. X
  787. X    if (v2->v_type != V_NUM)
  788. X        error("Bad epsilon type for abs");
  789. X    epsilon = v2->v_num;
  790. X    if (qiszero(epsilon) || qisneg(epsilon))
  791. X        error("Non-positive epsilon for abs");
  792. X    switch (v1->v_type) {
  793. X        case V_NUM:
  794. X            if (qisneg(v1->v_num))
  795. X                q = qneg(v1->v_num);
  796. X            else
  797. X                q = qlink(v1->v_num);
  798. X            break;
  799. X        case V_COM:
  800. X            q = qhypot(v1->v_com->real, v1->v_com->imag, epsilon);
  801. X            break;
  802. X        case V_OBJ:
  803. X            *vres = objcall(OBJ_ABS, v1, v2);
  804. X            return;
  805. X        default:
  806. X            error("Illegal value for absolute value");
  807. X    }
  808. X    vres->v_num = q;
  809. X    vres->v_type = V_NUM;
  810. X}
  811. X
  812. X
  813. X/*
  814. X * Calculate the norm of an arbitrary value.
  815. X * Result is placed in the indicated location.
  816. X * The norm is the square of the absolute value.
  817. X */
  818. Xvoid
  819. Xnormvalue(vp, vres)
  820. X    VALUE *vp, *vres;
  821. X{
  822. X    NUMBER *q1, *q2;
  823. X
  824. X    vres->v_type = V_NULL;
  825. X    switch (vp->v_type) {
  826. X        case V_NUM:
  827. X            vres->v_num = qsquare(vp->v_num);
  828. X            vres->v_type = V_NUM;
  829. X            return;
  830. X        case V_COM:
  831. X            q1 = qsquare(vp->v_com->real);
  832. X            q2 = qsquare(vp->v_com->imag);
  833. X            vres->v_num = qadd(q1, q2);
  834. X            vres->v_type = V_NUM;
  835. X            qfree(q1);
  836. X            qfree(q2);
  837. X            return;
  838. X        case V_OBJ:
  839. X            *vres = objcall(OBJ_NORM, vp);
  840. X            return;
  841. X        default:
  842. X            error("Illegal value for norm");
  843. X    }
  844. X}
  845. X
  846. X
  847. X/*
  848. X * Shift a value left or right by the specified number of bits.
  849. X * Negative shift value means shift the direction opposite the selected dir.
  850. X * Right shifts are defined to lose bits off the low end of the number.
  851. X * Result is placed in the indicated location.
  852. X */
  853. Xvoid
  854. Xshiftvalue(v1, v2, rightshift, vres)
  855. X    VALUE *v1, *v2, *vres;
  856. X    BOOL rightshift;    /* TRUE if shift right instead of left */
  857. X{
  858. X    COMPLEX *c;
  859. X    long n;
  860. X    VALUE tmp;
  861. X
  862. X    if (v2->v_type != V_NUM)
  863. X        error("Non-real shift value");
  864. X     if (qisfrac(v2->v_num))
  865. X        error("Non-integral shift value");
  866. X    if (v1->v_type != V_OBJ) {
  867. X        if (isbig(v2->v_num->num))
  868. X            error("Very large shift value");
  869. X        n = qtoi(v2->v_num);
  870. X    }
  871. X    if (rightshift)
  872. X        n = -n;
  873. X    switch (v1->v_type) {
  874. X        case V_NUM:
  875. X            vres->v_num = qshift(v1->v_num, n);
  876. X            vres->v_type = V_NUM;
  877. X            return;
  878. X        case V_COM:
  879. X            c = cshift(v1->v_com, n);
  880. X            if (!cisreal(c)) {
  881. X                vres->v_com = c;
  882. X                vres->v_type = V_COM;
  883. X                return;
  884. X            }
  885. X            vres->v_num = qlink(c->real);
  886. X            vres->v_type = V_NUM;
  887. X            comfree(c);
  888. X            return;
  889. X        case V_MAT:
  890. X            vres->v_mat = matshift(v1->v_mat, n);
  891. X            vres->v_type = V_MAT;
  892. X            return;
  893. X        case V_OBJ:
  894. X            if (!rightshift) {
  895. X                *vres = objcall(OBJ_SHIFT, v1, v2);
  896. X                return;
  897. X            }
  898. X            tmp.v_num = qneg(v2->v_num);
  899. X            tmp.v_type = V_NUM;
  900. X            *vres = objcall(OBJ_SHIFT, v1, &tmp);
  901. X            qfree(tmp.v_num);
  902. X            return;
  903. X        default:
  904. X            error("Bad value for shifting");
  905. X    }
  906. X}
  907. X
  908. X
  909. X/*
  910. X * Scale a value by a power of two.
  911. X * Result is placed in the indicated location.
  912. X */
  913. Xvoid
  914. Xscalevalue(v1, v2, vres)
  915. X    VALUE *v1, *v2, *vres;
  916. X{
  917. X    long n;
  918. X
  919. X    if (v2->v_type != V_NUM)
  920. X        error("Non-real scaling factor");
  921. X    if (qisfrac(v2->v_num))
  922. X        error("Non-integral scaling factor");
  923. X    if (v1->v_type != V_OBJ) {
  924. X        if (isbig(v2->v_num->num))
  925. X            error("Very large scaling factor");
  926. X        n = qtoi(v2->v_num);
  927. X    }
  928. X    switch (v1->v_type) {
  929. X        case V_NUM:
  930. X            vres->v_num = qscale(v1->v_num, n);
  931. X            vres->v_type = V_NUM;
  932. X            return;
  933. X        case V_COM:
  934. X            vres->v_com = cscale(v1->v_com, n);
  935. X            vres->v_type = V_NUM;
  936. X            return;
  937. X        case V_MAT:
  938. X            vres->v_mat = matscale(v1->v_mat, n);
  939. X            vres->v_type = V_MAT;
  940. X            return;
  941. X        case V_OBJ:
  942. X            *vres = objcall(OBJ_SCALE, v1, v2);
  943. X            return;
  944. X        default:
  945. X            error("Bad value for scaling");
  946. X    }
  947. X}
  948. X
  949. X
  950. X/*
  951. X * Raise a value to an integral power.
  952. X * Result is placed in the indicated location.
  953. X */
  954. Xvoid
  955. Xpowivalue(v1, v2, vres)
  956. X    VALUE *v1, *v2, *vres;
  957. X{
  958. X    NUMBER *q;
  959. X    COMPLEX *c;
  960. X
  961. X    vres->v_type = V_NULL;
  962. X    if (v2->v_type != V_NUM)
  963. X        error("Raising value to non-real power");
  964. X    q = v2->v_num;
  965. X    if (qisfrac(q))
  966. X        error("Raising value to non-integral power");
  967. X    switch (v1->v_type) {
  968. X        case V_NUM:
  969. X            vres->v_num = qpowi(v1->v_num, q);
  970. X            vres->v_type = V_NUM;
  971. X            return;
  972. X        case V_COM:
  973. X            vres->v_com = cpowi(v1->v_com, q);
  974. X            vres->v_type = V_COM;
  975. X            c = vres->v_com;
  976. X            if (!cisreal(c))
  977. X                return;
  978. X            vres->v_num = qlink(c->real);
  979. X            vres->v_type = V_NUM;
  980. X            comfree(c);
  981. X            return;
  982. X        case V_MAT:
  983. X            vres->v_mat = matpowi(v1->v_mat, q);
  984. X            vres->v_type = V_MAT;
  985. X            return;
  986. X        case V_OBJ:
  987. X            *vres = objcall(OBJ_POW, v1, v2);
  988. X            return;
  989. X        default:
  990. X            error("Illegal value for raising to integer power");
  991. X    }
  992. X}
  993. X
  994. X
  995. X/*
  996. X * Raise one value to another value's power, within the specified error.
  997. X * Result is placed in the indicated location.
  998. X */
  999. Xvoid
  1000. Xpowervalue(v1, v2, v3, vres)
  1001. X    VALUE *v1, *v2, *v3, *vres;
  1002. X{
  1003. X    NUMBER *epsilon;
  1004. X    COMPLEX *c, ctmp;
  1005. X
  1006. X    vres->v_type = V_NULL;
  1007. X    if (v3->v_type != V_NUM)
  1008. X        error("Non-real epsilon value for power");
  1009. X    epsilon = v3->v_num;
  1010. X    if (qisneg(epsilon) || qiszero(epsilon))
  1011. X        error("Non-positive epsilon value for power");
  1012. X    switch (TWOVAL(v1->v_type, v2->v_type)) {
  1013. X        case TWOVAL(V_NUM, V_NUM):
  1014. X            vres->v_num = qpower(v1->v_num, v2->v_num, epsilon);
  1015. X            vres->v_type = V_NUM;
  1016. X            return;
  1017. X        case TWOVAL(V_NUM, V_COM):
  1018. X            ctmp.real = v1->v_num;
  1019. X            ctmp.imag = &_qzero_;
  1020. X            vres->v_com = cpower(&ctmp, v2->v_com, epsilon);
  1021. X            break;
  1022. X        case TWOVAL(V_COM, V_NUM):
  1023. X            ctmp.real = v2->v_num;
  1024. X            ctmp.imag = &_qzero_;
  1025. X            vres->v_com = cpower(v1->v_com, &ctmp, epsilon);
  1026. X            break;
  1027. X        case TWOVAL(V_COM, V_COM):
  1028. X            vres->v_com = cpower(v1->v_com, v2->v_com, epsilon);
  1029. X            break;
  1030. X        default:
  1031. X            error("Illegal value for raising to power");
  1032. X    }
  1033. X    /*
  1034. X     * Here for any complex result.
  1035. X     */
  1036. X    vres->v_type = V_COM;
  1037. X    c = vres->v_com;
  1038. X    if (!cisreal(c))
  1039. X        return;
  1040. X    vres->v_num = qlink(c->real);
  1041. X    vres->v_type = V_NUM;
  1042. X    comfree(c);
  1043. X}
  1044. X
  1045. X
  1046. X/*
  1047. X * Divide one arbitrary value by another one.
  1048. X * Result is placed in the indicated location.
  1049. X */
  1050. Xvoid
  1051. Xdivvalue(v1, v2, vres)
  1052. X    VALUE *v1, *v2, *vres;
  1053. X{
  1054. X    COMPLEX *c;
  1055. X    COMPLEX tmp;
  1056. X    VALUE tmpval;
  1057. X
  1058. X    vres->v_type = V_NULL;
  1059. X    switch (TWOVAL(v1->v_type, v2->v_type)) {
  1060. X        case TWOVAL(V_NUM, V_NUM):
  1061. X            vres->v_num = qdiv(v1->v_num, v2->v_num);
  1062. X            vres->v_type = V_NUM;
  1063. X            return;
  1064. X        case TWOVAL(V_COM, V_NUM):
  1065. X            vres->v_com = cdivq(v1->v_com, v2->v_num);
  1066. X            vres->v_type = V_COM;
  1067. X            return;
  1068. X        case TWOVAL(V_NUM, V_COM):
  1069. X            if (qiszero(v1->v_num)) {
  1070. X                vres->v_num = qlink(&_qzero_);
  1071. X                vres->v_type = V_NUM;
  1072. X                return;
  1073. X            }
  1074. X            tmp.real = v1->v_num;
  1075. X            tmp.imag = &_qzero_;
  1076. X            vres->v_com = cdiv(&tmp, v2->v_com);
  1077. X            vres->v_type = V_COM;
  1078. X            return;
  1079. X        case TWOVAL(V_COM, V_COM):
  1080. X            vres->v_com = cdiv(v1->v_com, v2->v_com);
  1081. X            vres->v_type = V_COM;
  1082. X            c = vres->v_com;
  1083. X            if (cisreal(c)) {
  1084. X                vres->v_num = qlink(c->real);
  1085. X                vres->v_type = V_NUM;
  1086. X                comfree(c);
  1087. X            }
  1088. X            return;
  1089. X        case TWOVAL(V_MAT, V_NUM):
  1090. X        case TWOVAL(V_MAT, V_COM):
  1091. X            invertvalue(v2, &tmpval);
  1092. X            vres->v_mat = matmulval(v1->v_mat, &tmpval);
  1093. X            vres->v_type = V_MAT;
  1094. X            freevalue(&tmpval);
  1095. X            return;
  1096. X        default:
  1097. X            if ((v1->v_type != V_OBJ) && (v2->v_type != V_OBJ))
  1098. X                error("Non-compatible values for divide");
  1099. X            *vres = objcall(OBJ_DIV, v1, v2);
  1100. X            return;
  1101. X    }
  1102. X}
  1103. X
  1104. X
  1105. X/*
  1106. X * Divide one arbitrary value by another one keeping only the integer part.
  1107. X * Result is placed in the indicated location.
  1108. X */
  1109. Xvoid
  1110. Xquovalue(v1, v2, vres)
  1111. X    VALUE *v1, *v2, *vres;
  1112. X{
  1113. X    COMPLEX *c;
  1114. X
  1115. X    vres->v_type = V_NULL;
  1116. X    switch (TWOVAL(v1->v_type, v2->v_type)) {
  1117. X        case TWOVAL(V_NUM, V_NUM):
  1118. X            vres->v_num = qquo(v1->v_num, v2->v_num);
  1119. X            vres->v_type = V_NUM;
  1120. X            return;
  1121. X        case TWOVAL(V_COM, V_NUM):
  1122. X            vres->v_com = cquoq(v1->v_com, v2->v_num);
  1123. X            vres->v_type = V_COM;
  1124. X            c = vres->v_com;
  1125. X            if (cisreal(c)) {
  1126. X                vres->v_num = qlink(c->real);
  1127. X                vres->v_type = V_NUM;
  1128. X                comfree(c);
  1129. X            }
  1130. X            return;
  1131. X        case TWOVAL(V_MAT, V_NUM):
  1132. X        case TWOVAL(V_MAT, V_COM):
  1133. X            vres->v_mat = matquoval(v1->v_mat, v2);
  1134. X            vres->v_type = V_MAT;
  1135. X            return;
  1136. X        default:
  1137. X            if ((v1->v_type != V_OBJ) && (v2->v_type != V_OBJ))
  1138. X                error("Non-compatible values for quotient");
  1139. X            *vres = objcall(OBJ_QUO, v1, v2);
  1140. X            return;
  1141. X    }
  1142. X}
  1143. X
  1144. X
  1145. X/*
  1146. X * Divide one arbitrary value by another one keeping only the remainder.
  1147. X * Result is placed in the indicated location.
  1148. X */
  1149. Xvoid
  1150. Xmodvalue(v1, v2, vres)
  1151. X    VALUE *v1, *v2, *vres;
  1152. X{
  1153. X    COMPLEX *c;
  1154. X
  1155. X    vres->v_type = V_NULL;
  1156. X    switch (TWOVAL(v1->v_type, v2->v_type)) {
  1157. X        case TWOVAL(V_NUM, V_NUM):
  1158. X            vres->v_num = qmod(v1->v_num, v2->v_num);
  1159. X            vres->v_type = V_NUM;
  1160. X            return;
  1161. X        case TWOVAL(V_COM, V_NUM):
  1162. X            vres->v_com = cmodq(v1->v_com, v2->v_num);
  1163. X            vres->v_type = V_COM;
  1164. X            c = vres->v_com;
  1165. X            if (cisreal(c)) {
  1166. X                vres->v_num = qlink(c->real);
  1167. X                vres->v_type = V_NUM;
  1168. X                comfree(c);
  1169. X            }
  1170. X            return;
  1171. X        case TWOVAL(V_MAT, V_NUM):
  1172. X        case TWOVAL(V_MAT, V_COM):
  1173. X            vres->v_mat = matmodval(v1->v_mat, v2);
  1174. X            vres->v_type = V_MAT;
  1175. X            return;
  1176. X        default:
  1177. X            if ((v1->v_type != V_OBJ) && (v2->v_type != V_OBJ))
  1178. X                error("Non-compatible values for mod");
  1179. X            *vres = objcall(OBJ_MOD, v1, v2);
  1180. X            return;
  1181. X    }
  1182. X}
  1183. X
  1184. X
  1185. X/*
  1186. X * Test an arbitrary value to see if it is equal to "zero".
  1187. X * The definition of zero varies depending on the value type.  For example,
  1188. X * the null string is "zero", and a matrix with zero values is "zero".
  1189. X * Returns TRUE if value is not equal to zero.
  1190. X */
  1191. XBOOL
  1192. Xtestvalue(vp)
  1193. X    VALUE *vp;
  1194. X{
  1195. X    VALUE val;
  1196. X
  1197. X    switch (vp->v_type) {
  1198. X        case V_NUM:
  1199. X            return !qiszero(vp->v_num);
  1200. X        case V_COM:
  1201. X            return !ciszero(vp->v_com);
  1202. X        case V_STR:
  1203. X            return (vp->v_str[0] != '\0');
  1204. X        case V_MAT:
  1205. X            return mattest(vp->v_mat);
  1206. X        case V_LIST:
  1207. X            return (vp->v_list->l_count != 0);
  1208. X        case V_FILE:
  1209. X            return validid(vp->v_file);
  1210. X        case V_NULL:
  1211. X            return FALSE;
  1212. X        case V_OBJ:
  1213. X            val = objcall(OBJ_TEST, vp);
  1214. X            return (val.v_int != 0);
  1215. X        default:
  1216. X            return TRUE;
  1217. X    }
  1218. X}
  1219. X
  1220. X
  1221. X/*
  1222. X * Compare two values for equality.
  1223. X * Returns TRUE if the two values differ.
  1224. X */
  1225. XBOOL
  1226. Xcomparevalue(v1, v2)
  1227. X    VALUE *v1, *v2;
  1228. X{
  1229. X    int r;
  1230. X    VALUE val;
  1231. X
  1232. X    if ((v1->v_type == V_OBJ) || (v2->v_type == V_OBJ)) {
  1233. X        val = objcall(OBJ_CMP, v1, v2);
  1234. X        return (val.v_int != 0);
  1235. X    }
  1236. X    if (v1 == v2)
  1237. X        return FALSE;
  1238. X    if (v1->v_type != v2->v_type)
  1239. X        return TRUE;
  1240. X    switch (v1->v_type) {
  1241. X        case V_NUM:
  1242. X            r = qcmp(v1->v_num, v2->v_num);
  1243. X            break;
  1244. X        case V_COM:
  1245. X            r = ccmp(v1->v_com, v2->v_com);
  1246. X            break;
  1247. X        case V_STR:
  1248. X            r = ((v1->v_str != v2->v_str) &&
  1249. X                ((v1->v_str[0] - v2->v_str[0]) ||
  1250. X                strcmp(v1->v_str, v2->v_str)));
  1251. X            break;
  1252. X        case V_MAT:
  1253. X            r = matcmp(v1->v_mat, v2->v_mat);
  1254. X            break;
  1255. X        case V_LIST:
  1256. X            r = listcmp(v1->v_list, v2->v_list);
  1257. X            break;
  1258. X        case V_NULL:
  1259. X            r = FALSE;
  1260. X            break;
  1261. X        case V_FILE:
  1262. X            r = (v1->v_file != v2->v_file);
  1263. X            break;
  1264. X        default:
  1265. X            error("Illegal values for comparevalue");
  1266. X    }
  1267. X    return (r != 0);
  1268. X}
  1269. X
  1270. X
  1271. X/*
  1272. X * Compare two values for their relative values.
  1273. X * Returns minus one if the first value is less than the second one,
  1274. X * one if the first value is greater than the second one, and
  1275. X * zero if they are equal.
  1276. X */
  1277. XFLAG
  1278. Xrelvalue(v1, v2)
  1279. X    VALUE *v1, *v2;
  1280. X{
  1281. X    int r;
  1282. X    VALUE val;
  1283. X
  1284. X    if ((v1->v_type == V_OBJ) || (v2->v_type == V_OBJ)) {
  1285. X        val = objcall(OBJ_REL, v1, v2);
  1286. X        return val.v_int;
  1287. X    }
  1288. X    if (v1 == v2)
  1289. X        return 0;
  1290. X    if (v1->v_type != v2->v_type)
  1291. X        error("Relative comparison of differing types");
  1292. X    switch (v1->v_type) {
  1293. X        case V_NUM:
  1294. X            r = qrel(v1->v_num, v2->v_num);
  1295. X            break;
  1296. X        case V_STR:
  1297. X            r = strcmp(v1->v_str, v2->v_str);
  1298. X            break;
  1299. X        case V_NULL:
  1300. X            r = 0;
  1301. X            break;
  1302. X        default:
  1303. X            error("Illegal value for relative comparison");
  1304. X    }
  1305. X    if (r < 0)
  1306. X        return -1;
  1307. X    return (r != 0);
  1308. X}
  1309. X
  1310. X
  1311. X/*
  1312. X * Print the value of a descriptor in one of several formats.
  1313. X * If flags contains PRINT_SHORT, then elements of arrays and lists
  1314. X * will not be printed.  If flags contains PRINT_UNAMBIG, then quotes
  1315. X * are placed around strings and the null value is explicitly printed.
  1316. X */
  1317. Xvoid
  1318. Xprintvalue(vp, flags)
  1319. X    VALUE *vp;
  1320. X{
  1321. X    switch (vp->v_type) {
  1322. X        case V_NUM:
  1323. X            qprintnum(vp->v_num, MODE_DEFAULT);
  1324. X            break;
  1325. X        case V_COM:
  1326. X            comprint(vp->v_com);
  1327. X            break;
  1328. X        case V_STR:
  1329. X            if (flags & PRINT_UNAMBIG)
  1330. X                math_chr('\"');
  1331. X            math_str(vp->v_str);
  1332. X            if (flags & PRINT_UNAMBIG)
  1333. X                math_chr('\"');
  1334. X            break;
  1335. X        case V_NULL:
  1336. X            if (flags & PRINT_UNAMBIG)
  1337. X                math_str("NULL");
  1338. X            break;
  1339. X        case V_OBJ:
  1340. X            (void) objcall(OBJ_PRINT, vp);
  1341. X            break;
  1342. X        case V_LIST:
  1343. X            listprint(vp->v_list,
  1344. X                ((flags & PRINT_SHORT) ? 0L : maxprint));
  1345. X            break;
  1346. X        case V_MAT:
  1347. X            matprint(vp->v_mat,
  1348. X                ((flags & PRINT_SHORT) ? 0L : maxprint));
  1349. X            break;
  1350. X        case V_FILE:
  1351. X            printid(vp->v_file, flags);
  1352. X            break;
  1353. X        default:
  1354. X            error("Printing unknown value");
  1355. X    }
  1356. X}
  1357. X
  1358. X/* END CODE */
  1359. END_OF_FILE
  1360. if test 27747 -ne `wc -c <'value.c'`; then
  1361.     echo shar: \"'value.c'\" unpacked with wrong size!
  1362. fi
  1363. # end of 'value.c'
  1364. fi
  1365. echo shar: End of archive 12 \(of 21\).
  1366. cp /dev/null ark12isdone
  1367. MISSING=""
  1368. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ; do
  1369.     if test ! -f ark${I}isdone ; then
  1370.     MISSING="${MISSING} ${I}"
  1371.     fi
  1372. done
  1373. if test "${MISSING}" = "" ; then
  1374.     echo You have unpacked all 21 archives.
  1375.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1376. else
  1377.     echo You still need to unpack the following archives:
  1378.     echo "        " ${MISSING}
  1379. fi
  1380. ##  End of shell archive.
  1381. exit 0
  1382.