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

  1. Newsgroups: comp.sources.unix
  2. From: dbell@pdact.pd.necisa.oz.au (David I. Bell)
  3. Subject: v26i028: CALC - An arbitrary precision C-like calculator, Part02/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 28
  9. Archive-Name: calc/part02
  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 2 (of 21)."
  18. # Contents:  alloc.h calc.c const.c help/command help/config
  19. #   help/define help/mat help/types label.c lib/README lib/mod.cal
  20. #   lib/poly.cal lib/quat.cal
  21. # Wrapped by dbell@elm on Tue Feb 25 15:20:55 1992
  22. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  23. if test -f 'alloc.h' -a "${1}" != "-c" ; then 
  24.   echo shar: Will not clobber existing file \"'alloc.h'\"
  25. else
  26. echo shar: Extracting \"'alloc.h'\" \(2686 characters\)
  27. sed "s/^X//" >'alloc.h' <<'END_OF_FILE'
  28. X/*
  29. X * Copyright (c) 1992 David I. Bell
  30. X * Permission is granted to use, distribute, or modify this source,
  31. X * provided that this copyright notice remains intact.
  32. X *
  33. X * Allocator definitions (fast malloc and free)
  34. X */
  35. X
  36. X#if defined(UNIX_MALLOC)
  37. X
  38. X#include "have_malloc.h"
  39. X#ifdef HAVE_MALLOC_H
  40. X# include <malloc.h>
  41. X#else
  42. X# if defined(__STDC__)
  43. X   extern void *malloc();
  44. X   extern void *realloc();
  45. X   extern void free();
  46. X# else
  47. X   extern char *malloc();
  48. X   extern char *realloc();
  49. X   extern void free();
  50. X# endif
  51. X#endif
  52. X
  53. X#include "have_string.h"
  54. X
  55. X#ifdef HAVE_STRING_H
  56. X# include <string.h>
  57. X
  58. X#else
  59. X
  60. X# ifdef OLD_BSD
  61. Xextern void bcopy();
  62. Xextern void bfill();
  63. Xextern char *index();
  64. X# else /* OLD_BSD */
  65. Xextern void memcpy();
  66. Xextern void memset();
  67. X#  if defined(__STDC__)
  68. Xextern void *strchr();
  69. X#  else
  70. Xextern char *strchr();
  71. X#  endif
  72. X# endif /* OLD_BSD */
  73. Xextern void strcpy();
  74. Xextern void strncpy();
  75. Xextern void strcat();
  76. Xextern int strcmp();
  77. Xextern long strlen();    /* should be size_t, but old systems don't have it */
  78. X
  79. X#endif
  80. X
  81. X#ifdef OLD_BSD
  82. X#undef memcpy
  83. X#define memcpy(s1, s2, n) bcopy(s2, s1, n)
  84. X#undef memset
  85. X#define memset(s, c, n) bfill(s, n, c)
  86. X#undef strchr
  87. X#define strchr(s, c) index(s, c)
  88. X#endif
  89. X
  90. X#ifdef VSPRINTF
  91. X/*
  92. X * XXX - hack aleart
  93. X *
  94. X * Systems that do not have vsprintf() need something.  In some cases
  95. X * the sprintf function will deal correctly with the va_alist 3rd arg.
  96. X * Hope for the best!
  97. X */
  98. X#define vsprintf sprintf
  99. X#endif
  100. X
  101. Xextern void exit();
  102. X
  103. X#define mem_alloc malloc
  104. X#define mem_realloc realloc
  105. X#define mem_free free
  106. X
  107. X#else /*UNIX_MALLOC*/
  108. X
  109. X#define malloc(a) mem_alloc((long) a)
  110. X#define realloc(a,b) mem_realloc((char *) a, (long) b)
  111. X#define free(a) mem_free((char *) a)
  112. Xextern char *mem_alloc();
  113. Xextern char *mem_realloc();
  114. Xextern int mem_free();        /* MUST be int even though no return value */
  115. X
  116. X#endif /*UNIX_MALLOC*/
  117. X
  118. X
  119. X/*
  120. X * An item to be placed on a free list.
  121. X * These items are overlayed on top of the actual item being managed.
  122. X * Therefore, the managed items must be at least this size!
  123. X * Also, all items on a single free list must be the same size.
  124. X */
  125. Xstruct free_item {
  126. X    struct free_item *next;            /* next item on free list */
  127. X};
  128. Xtypedef struct free_item FREEITEM;
  129. X
  130. X
  131. X/*
  132. X * The actual free list header.
  133. X */
  134. Xtypedef struct {
  135. X    long        itemsize;    /* size of an item being managed */
  136. X    long        maxfree;    /* maximum number of free items */
  137. X    long        curfree;    /* current number of free items */
  138. X    FREEITEM    *freelist;    /* the free list */
  139. X} FREELIST;
  140. X
  141. X#if defined(__STDC__)
  142. Xtypedef void ALLOCITEM;
  143. X#else
  144. Xtypedef char ALLOCITEM;
  145. X#endif
  146. Xextern ALLOCITEM * allocitem( /* FREELIST * */ );
  147. Xextern void freeitem( /* FREELIST *, char * */ );
  148. Xextern void mem_stats();
  149. X
  150. X/* END CODE */
  151. END_OF_FILE
  152. if test 2686 -ne `wc -c <'alloc.h'`; then
  153.     echo shar: \"'alloc.h'\" unpacked with wrong size!
  154. fi
  155. # end of 'alloc.h'
  156. fi
  157. if test -f 'calc.c' -a "${1}" != "-c" ; then 
  158.   echo shar: Will not clobber existing file \"'calc.c'\"
  159. else
  160. echo shar: Extracting \"'calc.c'\" \(4905 characters\)
  161. sed "s/^X//" >'calc.c' <<'END_OF_FILE'
  162. X/*
  163. X * Copyright (c) 1992 David I. Bell
  164. X * Permission is granted to use, distribute, or modify this source,
  165. X * provided that this copyright notice remains intact.
  166. X *
  167. X * Arbitrary precision calculator.
  168. X */
  169. X
  170. X#include <signal.h>
  171. X#include <pwd.h>
  172. X#include <sys/types.h>
  173. X
  174. X#include "calc.h"
  175. X#include "func.h"
  176. X#include "opcodes.h"
  177. X#include "config.h"
  178. X#include "token.h"
  179. X#include "symbol.h"
  180. X
  181. X/*
  182. X * Common definitions
  183. X */
  184. Xlong maxprint;        /* number of elements to print */
  185. Xint abortlevel;        /* current level of aborts */
  186. XBOOL inputwait;        /* TRUE if in a terminal input wait */
  187. Xjmp_buf jmpbuf;        /* for errors */
  188. X
  189. Xstatic int q_flag = FALSE;    /* TRUE => don't execute rc files */
  190. X
  191. Xchar *calcpath;        /* $CALCPATH or default */
  192. Xchar *calcrc;        /* $CALCRC or default */
  193. Xchar *home;        /* $HOME or default */
  194. Xstatic char *pager;    /* $PAGER or default */
  195. Xchar *shell;        /* $SHELL or default */
  196. X
  197. Xstatic void intint();    /* interrupt routine */
  198. Xvoid givehelp();
  199. Xstatic void initenv();    /* initialize/default special environment vars */
  200. X
  201. Xextern struct passwd *getpwuid();
  202. Xextern char *getenv();
  203. Xextern uid_t geteuid();
  204. X
  205. X/*
  206. X * Top level calculator routine.
  207. X */
  208. Xmain(argc, argv)
  209. X    char **argv;
  210. X{
  211. X    char *str;        /* current option string or expression */
  212. X    char cmdbuf[MAXCMD+1];    /* command line expression */
  213. X
  214. X    initenv();
  215. X    argc--;
  216. X    argv++;
  217. X    while ((argc > 0) && (**argv == '-')) {
  218. X        for (str = &argv[0][1]; *str; str++) switch (*str) {
  219. X            case 'h':
  220. X                givehelp(DEFAULTCALCHELP);
  221. X                exit(0);
  222. X                break;
  223. X            case 'q':
  224. X                q_flag = TRUE;
  225. X                break;
  226. X            default:
  227. X                printf("Unknown option\n");
  228. X                exit(1);
  229. X        }
  230. X        argc--;
  231. X        argv++;
  232. X    }
  233. X    str = cmdbuf;
  234. X    *str = '\0';
  235. X    while (--argc >= 0) {
  236. X        *str++ = ' ';
  237. X        strcpy(str, *argv++);
  238. X        str += strlen(str);
  239. X        str[0] = '\n';
  240. X        str[1] = '\0';
  241. X    }
  242. X    str = cmdbuf;
  243. X    if (*str == '\0') {
  244. X        str = NULL;
  245. X        printf("C-style arbitrary precision calculator.\n");
  246. X        version(stdout);
  247. X        printf("[Type \"exit\" to exit, or \"help\" for help.]\n\n");
  248. X    }
  249. X    if (setjmp(jmpbuf) == 0) {
  250. X        initmasks();
  251. X        inittokens();
  252. X        initglobals();
  253. X        initfunctions();
  254. X        initstack();
  255. X        resetinput();
  256. X        cleardiversions();
  257. X        setfp(stdout);
  258. X        setmode(MODE_INITIAL);
  259. X        setdigits(DISPLAY_DEFAULT);
  260. X        maxprint = MAXPRINT_DEFAULT;
  261. X        _epsilon_ = atoq(EPSILON_DEFAULT);
  262. X        _epsilonprec_ = qprecision(_epsilon_);
  263. X        if (str) {
  264. X            if (q_flag == FALSE) {
  265. X                runrcfiles();
  266. X                q_flag = TRUE;
  267. X            }
  268. X            (void) openstring(str);
  269. X            getcommands();
  270. X            exit(0);
  271. X        }
  272. X    }
  273. X    if (str)
  274. X        exit(1);
  275. X    abortlevel = 0;
  276. X    _math_abort_ = FALSE;
  277. X    inputwait = FALSE;
  278. X    (void) signal(SIGINT, intint);
  279. X    cleardiversions();
  280. X    setfp(stdout);
  281. X    resetinput();
  282. X    if (q_flag == FALSE) {
  283. X        runrcfiles();
  284. X        q_flag = TRUE;
  285. X    }
  286. X    (void) openterminal();
  287. X    getcommands();
  288. X    exit(0);
  289. X    /*NOTREACHED*/
  290. X}
  291. X
  292. X
  293. X/*
  294. X * initenv - obtain $CALCPATH, $CALCRC, $HOME, $PAGER and $SHELL values
  295. X *
  296. X * If $CALCPATH, $CALCRC, $PAGER or $SHELL do not exist, use the default
  297. X * values.  If $PAGER or $SHELL is an empty string, also use a default value.
  298. X * If $HOME does not exist, or is empty, use the home directory
  299. X * information from the password file.
  300. X */
  301. Xstatic void
  302. Xinitenv()
  303. X{
  304. X    struct passwd *ent;        /* our password entry */
  305. X
  306. X    /* determine the $CALCPATH value */
  307. X    calcpath = getenv(CALCPATH);
  308. X    if (calcpath == NULL)
  309. X        calcpath = DEFAULTCALCPATH;
  310. X
  311. X    /* determine the $CALCRC value */
  312. X    calcrc = getenv(CALCRC);
  313. X    if (calcrc == NULL) {
  314. X        calcrc = DEFAULTCALCRC;
  315. X    }
  316. X    
  317. X    /* determine the $HOME value */
  318. X    home = getenv(HOME);
  319. X    if (home == NULL || home[0] == '\0') {
  320. X        ent = getpwuid(geteuid());
  321. X        if (ent == NULL) {
  322. X            /* just assume . is home if all else fails */
  323. X            home = ".";
  324. X        }
  325. X        home = (char *)malloc(strlen(ent->pw_dir)+1);
  326. X        strcpy(home, ent->pw_dir);
  327. X    }
  328. X
  329. X    /* determine the $PAGER value */
  330. X    pager = getenv(PAGER);
  331. X    if (pager == NULL || *pager == '\0') {
  332. X        pager = DEFAULTCALCPAGER;
  333. X    }
  334. X
  335. X    /* determine the $SHELL value */
  336. X    shell = getenv(SHELL);
  337. X    if (shell == NULL)
  338. X        shell = DEFAULTSHELL;
  339. X}
  340. X
  341. Xvoid
  342. Xgivehelp(type)
  343. X    char *type;        /* the type of help to give, NULL => index */
  344. X{
  345. X    char *helpcmd;        /* what to execute to print help */
  346. X
  347. X    /* catch the case where we just print the index */
  348. X    if (type == NULL) {
  349. X        type = DEFAULTCALCHELP;        /* the help index file */
  350. X    }
  351. X
  352. X    /* form the help command name */
  353. X    helpcmd = (char *)malloc(
  354. X        sizeof("if [ ! -d \"")+sizeof(HELPDIR)+1+strlen(type)+
  355. X        sizeof("\" ];then ")+
  356. X        strlen(pager)+1+1+sizeof(HELPDIR)+1+strlen(type)+1+1+
  357. X        sizeof(";else echo no such help;fi"));
  358. X    sprintf(helpcmd, 
  359. X        "if [ -r \"%s/%s\" ];then %s \"%s/%s\";else echo no such help;fi", 
  360. X        HELPDIR, type, pager, HELPDIR, type);
  361. X
  362. X    /* execute the help command */
  363. X    system(helpcmd);
  364. X    free(helpcmd);
  365. X}
  366. X
  367. X
  368. X/*
  369. X * Interrupt routine.
  370. X */
  371. X/*ARGSUSED*/
  372. Xstatic void
  373. Xintint(arg)
  374. X    int arg;    /* to keep ANSI C happy */
  375. X{
  376. X    (void) signal(SIGINT, intint);
  377. X    if (inputwait || (++abortlevel >= ABORT_NOW))
  378. X        error("\nABORT");
  379. X    if (abortlevel >= ABORT_MATH)
  380. X        _math_abort_ = TRUE;
  381. X    printf("\n[Abort level %d]\n", abortlevel);
  382. X}
  383. X
  384. X/* END CODE */
  385. END_OF_FILE
  386. if test 4905 -ne `wc -c <'calc.c'`; then
  387.     echo shar: \"'calc.c'\" unpacked with wrong size!
  388. fi
  389. # end of 'calc.c'
  390. fi
  391. if test -f 'const.c' -a "${1}" != "-c" ; then 
  392.   echo shar: Will not clobber existing file \"'const.c'\"
  393. else
  394. echo shar: Extracting \"'const.c'\" \(2709 characters\)
  395. sed "s/^X//" >'const.c' <<'END_OF_FILE'
  396. X/*
  397. X * Copyright (c) 1992 David I. Bell
  398. X * Permission is granted to use, distribute, or modify this source,
  399. X * provided that this copyright notice remains intact.
  400. X *
  401. X * Constant number storage module.
  402. X */
  403. X
  404. X#include "calc.h"
  405. X
  406. X#define CONSTALLOCSIZE 400    /* number of constants to allocate */
  407. X
  408. X
  409. Xstatic long constcount;        /* number of constants defined */
  410. Xstatic long constavail;        /* number of constants available */
  411. Xstatic NUMBER **consttable;    /* table of constants */
  412. X
  413. X
  414. X/*
  415. X * Read in a constant number and add it to the table of constant numbers,
  416. X * creating a new entry if necessary.  The incoming number is a string
  417. X * value which must have a correct format, otherwise an undefined number
  418. X * will result.  Returns the index of the number in the constant table.
  419. X * Returns zero if the number could not be saved.
  420. X */
  421. Xlong
  422. Xaddnumber(str)
  423. X    char *str;        /* string representation of number */
  424. X{
  425. X    NUMBER *q;
  426. X
  427. X    q = atoq(str);
  428. X    if (q == NULL)
  429. X        return 0;
  430. X    return addqconstant(q);
  431. X}
  432. X
  433. X
  434. X/*
  435. X * Add a particular number to the constant table.
  436. X * Returns the index of the number in the constant table, or zero
  437. X * if the number could not be saved.  The incoming number if freed
  438. X * if it is already in the table.
  439. X */
  440. Xlong
  441. Xaddqconstant(q)
  442. X    register NUMBER *q;    /* number to be added */
  443. X{
  444. X    register NUMBER **tp;    /* pointer to current number */
  445. X    register NUMBER *t;    /* number being tested */
  446. X    long index;        /* index into constant table */
  447. X    long numlen;        /* numerator length */
  448. X    long denlen;        /* denominator length */
  449. X    HALF numlow;        /* bottom value of numerator */
  450. X    HALF denlow;        /* bottom value of denominator */
  451. X
  452. X    numlen = q->num.len;
  453. X    denlen = q->den.len;
  454. X    numlow = q->num.v[0];
  455. X    denlow = q->den.v[0];
  456. X    tp = &consttable[1];
  457. X    for (index = 1; index <= constcount; index++) {
  458. X        t = *tp++;
  459. X        if ((numlen != t->num.len) || (numlow != t->num.v[0]))
  460. X            continue;
  461. X        if ((denlen != t->den.len) || (denlow != t->den.v[0]))
  462. X            continue;
  463. X        if (q->num.sign != t->num.sign)
  464. X            continue;
  465. X        if (qcmp(q, t) == 0) {
  466. X            qfree(q);
  467. X            return index;
  468. X        }
  469. X    }
  470. X    if (constavail <= 0) {
  471. X        if (consttable == NULL) {
  472. X            tp = (NUMBER **)
  473. X                malloc(sizeof(NUMBER *) * (CONSTALLOCSIZE + 1));
  474. X            *tp = NULL;
  475. X        } else
  476. X            tp = (NUMBER **) realloc((char *) consttable,
  477. X            sizeof(NUMBER *) * (constcount+CONSTALLOCSIZE + 1));
  478. X        if (tp == NULL)
  479. X            return 0;
  480. X        consttable = tp;
  481. X        constavail = CONSTALLOCSIZE;
  482. X    }
  483. X    constavail--;
  484. X    constcount++;
  485. X    consttable[constcount] = q;
  486. X    return constcount;
  487. X}
  488. X
  489. X
  490. X/*
  491. X * Return the value of a constant number given its index.
  492. X * Returns address of the number, or NULL if the index is illegal.
  493. X */
  494. XNUMBER *
  495. Xconstvalue(index)
  496. X    long index;
  497. X{
  498. X    if ((index <= 0) || (index > constcount))
  499. X        return NULL;
  500. X    return consttable[index];
  501. X}
  502. X
  503. X/* END CODE */
  504. END_OF_FILE
  505. if test 2709 -ne `wc -c <'const.c'`; then
  506.     echo shar: \"'const.c'\" unpacked with wrong size!
  507. fi
  508. # end of 'const.c'
  509. fi
  510. if test -f 'help/command' -a "${1}" != "-c" ; then 
  511.   echo shar: Will not clobber existing file \"'help/command'\"
  512. else
  513. echo shar: Extracting \"'help/command'\" \(2740 characters\)
  514. sed "s/^X//" >'help/command' <<'END_OF_FILE'
  515. XCommand sequence
  516. X
  517. X    This is a sequence of any the following command formats, where
  518. X    each command is terminated by a semicolon or newline.  Long command
  519. X    lines can be extended by using a back-slash followed by a newline
  520. X    character.  When this is done, the prompt shows a double angle
  521. X    bracket to indicate that the line is still in progress.  Certain
  522. X    cases will automatically prompt for more input in a similar manner,
  523. X    even without the back-slash.  The most common case for this is when
  524. X    a function is being defined, but is not yet completed.
  525. X
  526. X    Each command sequence terminates only on an end of file.  In
  527. X    addition, commands can consist of expression sequences, which are
  528. X    described in the next section.
  529. X
  530. X
  531. X    NOTE: Calc commands are in lower case.   UPPER case is used below
  532. X          for emphasis only, and should be considered in lower case.
  533. X
  534. X
  535. X    DEFINE function(params) { body }
  536. X    DEFINE function(params) = expression
  537. X        This first form defines a full function which can consist
  538. X        of declarations followed by many statements which implement
  539. X        the function.
  540. X
  541. X        The second form defines a simple function which calculates
  542. X        the specified expression value from the specified parameters.
  543. X        The expression cannot be a statement.  However, the comma
  544. X        and question mark operators can be useful.  Examples of
  545. X        simple functions are:
  546. X
  547. X            define sumcubes(a, b) = a^3 + b^3;
  548. X            define pimod(a) = a % pi();
  549. X
  550. X    HELP
  551. X        This displays a general help message.
  552. X
  553. X    READ filename
  554. X        This reads definitions from the specified filename.
  555. X        The name can be quoted if desired.  The calculator
  556. X        uses the CALCPATH environment variable to search
  557. X        through the specified directories for the filename,
  558. X        similarly to the use of the PATH environment variable.
  559. X        If CALCPATH is not defined, then a default path of
  560. X        ":/usr/lib/calc" is used (that is, the current directory
  561. X        followed by a general calc library directory).  The
  562. X        ".cal" extension is defaulted for input files, so that
  563. X        if "filename" is not found, then "filename.cal" is then
  564. X        searched for.  The contents of the filename are command
  565. X        sequences which can consist of expressions to evaluate
  566. X        or functions to define, just like at the top level
  567. X        command level.
  568. X
  569. X    WRITE filename
  570. X        This writes the values of all global variables to the
  571. X        specified filename, in such a way that the file can be
  572. X        later read in order to recreate the variable values.
  573. X        For speed reasons, values are written as hex fractions.
  574. X        This command currently only saves simple types, so that
  575. X        matrices, lists, and objects are not saved.  Function
  576. X        definitions are also not saved.
  577. X
  578. X    QUIT
  579. X        This leaves the calculator, when given as a top-level
  580. X        command.
  581. X    
  582. X
  583. X    Also see the help topic:
  584. X
  585. X        statement       flow control and declaration statements
  586. END_OF_FILE
  587. if test 2740 -ne `wc -c <'help/command'`; then
  588.     echo shar: \"'help/command'\" unpacked with wrong size!
  589. fi
  590. # end of 'help/command'
  591. fi
  592. if test -f 'help/config' -a "${1}" != "-c" ; then 
  593.   echo shar: Will not clobber existing file \"'help/config'\"
  594. else
  595. echo shar: Extracting \"'help/config'\" \(4426 characters\)
  596. sed "s/^X//" >'help/config' <<'END_OF_FILE'
  597. XConfiguration parameters
  598. X
  599. X    Configuration parameters affect how the calculator performs certain
  600. X    operations, and affects all future calculations.  These parameters
  601. X    affect the accuracy of calculations, the displayed format of results,
  602. X    and which algorithms are used for calculations.  The parameters are
  603. X    read or set using the "config" built-in function.  The following
  604. X    parameters can be specified:
  605. X
  606. X        "trace"        turns tracing on or off (for debugging).
  607. X        "display"    sets number of digits in prints.
  608. X        "epsilon"    sets error value for transcendentals.
  609. X        "maxprint"    sets maximum number of elements printed.
  610. X        "mode"        sets printout mode.
  611. X        "mul2"        sets size for alternative multiply.
  612. X        "sq2"        sets size for alternative squaring.
  613. X        "pow2"        sets size for alternate powering.
  614. X        "redc2"        sets size for alternate REDC.
  615. X
  616. X    The use of the trace flag is for debugging, and its meaning may
  617. X    change in the future.  A value of 1 causes the calculator to print
  618. X    its internal opcodes as it executes functions.  A value of zero
  619. X    disables tracing again.
  620. X
  621. X    Display specifies how many digits after the decimal point should
  622. X    be printed when printing real or exponential numbers.  The initial
  623. X    display value is 20.  This parameter does not affect the accuracy
  624. X    of a calculation, since it only has meaning when printing results.
  625. X
  626. X    Epsilon specifies the required precision of calculations by
  627. X    setting the maximum allowed error for transcendental functions.
  628. X    The error is an absolute error value for many functions, but
  629. X    for some functions it is a relative error.  The initial value
  630. X    is 1e-20.  Functions which require an epsilon value accept an
  631. X    optional argument which overrides this default epsilon value for
  632. X    that single call.  The built-in function "epsilon" also can be
  633. X    used to read or set this value, and is provided for ease of use.
  634. X
  635. X    Mode specifies how numbers should be printed.  Mode is a string
  636. X    value indicating the printout method.  The initial mode is "real".
  637. X    Possible modes are:
  638. X
  639. X        "frac"        decimal fractions
  640. X        "int"        decimal integer
  641. X        "real"        decimal floating point
  642. X        "exp"        decimal exponential
  643. X        "hex"        hex fractions
  644. X        "oct"        octal fractions
  645. X        "bin"        binary fractions
  646. X
  647. X    Maxprint specifies the maximum number of elements to be displayed
  648. X    when a matrix or list is printed.  The initial value is 16 elements.
  649. X
  650. X    Mul2 and sq2 specify the sizes of numbers at which calc switches
  651. X    from its first to its second algorithm for multiplying and squaring.
  652. X    The first algorithm is the usual method of cross multiplying, which
  653. X    runs in a time of O(N^2).  The second method is a recursive and
  654. X    complicated method which runs in a time of O(N^1.585).  The argument
  655. X    for these parameters is the number of binary words at which the
  656. X    second algorithm begins to be used.  The minimum value is 2, and
  657. X    the maximum value is very large.  If 2 is used, then the recursive
  658. X    algorithm is used all the way down to single digits, which becomes
  659. X    slow since the recursion overhead is high.  If a number such as
  660. X    1000000 is used, then the recursive algorithm is never used, causing
  661. X    calculations for large numbers to slow down.  For a typical example
  662. X    on a 386, the two algorithms are about equal in speed for a value
  663. X    of 20, which is about 100 decimal digits.  A value of zero resets
  664. X    the parameter back to its default value.  Usually there is no need
  665. X    to change these parameters.
  666. X
  667. X    Pow2 specifies the sizes of numbers at which calc switches from
  668. X    its first to its second algorithm for calculating powers modulo
  669. X    another number.  The first algorithm for calculating modular powers
  670. X    is by repeated squaring and multiplying and dividing by the modulus.
  671. X    The second method uses the REDC algorithm given by Peter Montgomery
  672. X    which avoids divisions.  The argument for pow2 is the size of the
  673. X    modulus at which the second algorithm begins to be used.
  674. X
  675. X    Redc2 specifies the sizes of numbers at which calc switches from
  676. X    its first to its second algorithm when using the REDC algorithm.
  677. X    The first algorithm performs a multiply and a modular reduction
  678. X    together in one loop which runs in O(N^2).  The second algorithm
  679. X    does the REDC calculation using three multiplies, and runs in
  680. X    O(N^1.585).  The argument for redc2 is the size of the modulus at
  681. X    which the second algorithm begins to be used.
  682. X
  683. X    Examples of setting some parameters are:
  684. X
  685. X        config("mode", "exp");        exponential output
  686. X        config("display", 50);        50 digits of output
  687. X        epsilon(epsilon() / 8);        3 bits more accuracy
  688. END_OF_FILE
  689. if test 4426 -ne `wc -c <'help/config'`; then
  690.     echo shar: \"'help/config'\" unpacked with wrong size!
  691. fi
  692. # end of 'help/config'
  693. fi
  694. if test -f 'help/define' -a "${1}" != "-c" ; then 
  695.   echo shar: Will not clobber existing file \"'help/define'\"
  696. else
  697. echo shar: Extracting \"'help/define'\" \(2679 characters\)
  698. sed "s/^X//" >'help/define' <<'END_OF_FILE'
  699. XFunction definitions
  700. X
  701. X    Function definitions are introduced by the 'define' keyword.
  702. X    Other than this, the basic structure of a function is like in C.
  703. X    That is, parameters are specified for the function within parenthesis,
  704. X    the function body is introduced by a left brace, variables are
  705. X    declared for the function, statements implementing the function
  706. X    follow, and the function is ended with a right brace.
  707. X
  708. X    There are some subtle differences, however.  The types of parameters
  709. X    and variables are not defined at compile time, but instead are typed
  710. X    at runtime.  Thus there is no definitions needed to distinguish
  711. X    between integers, fractions, complex numbers, matrices, and so on.
  712. X    Thus when declaring parameters for a function, only the name of
  713. X    the parameter is needed.  Thus there are never any declarations
  714. X    between the function parameter list and the body of the function.
  715. X
  716. X    For example, the following function computes a factorial:
  717. X
  718. X        define factorial(n)
  719. X        {
  720. X            local    ans;
  721. X
  722. X            ans = 1;
  723. X            while (n > 1)
  724. X                ans *= n--;
  725. X            return ans;
  726. X        }
  727. X
  728. X    If a function is very simple and just returns a value, then the
  729. X    function can be defined in shortened manner by using an equals sign
  730. X    in place of the left brace.  In this case, the function declaration
  731. X    is terminated by a newline character, and its value is the specified
  732. X    expression.  Statements such as 'if' are not allowed.  An optional
  733. X    semicolon ending the expression is allowed.  As an example, the
  734. X    average of two numbers could be defined as:
  735. X
  736. X        define average(a, b) = (a + b) / 2;
  737. X
  738. X    Functions can be defined which can be very complex.  These can be
  739. X    defined on the command line if desired, but editing of partial
  740. X    functions is not possible past a single line.  If an error is made
  741. X    on a previous line, then the function must be finished (with probable
  742. X    errors) and reentered from the beginning.  Thus for complicated
  743. X    functions, it is best to use an editor to create the function in a
  744. X    file, and then enter the calculator and read in the file containing
  745. X    the definition.
  746. X
  747. X    The parameters of a function can be referenced by name, as in
  748. X    normal C usage, or by using the 'param' function.  This function
  749. X    returns the specified parameter of the function it is in, where
  750. X    the parameters are numbered starting from 1.  The total number
  751. X    of parameters to the function is returned by using 'param(0)'.
  752. X    Using this function allows you to implement varargs-like routines
  753. X    which can handle any number of calling parameters.  For example:
  754. X
  755. X        define sc()
  756. X        {
  757. X            local s, i;
  758. X
  759. X            s = 0;
  760. X            for (i = 1; i <= param(0); i++)
  761. X                s += param(i)^3;
  762. X            return s;
  763. X        }
  764. X
  765. X    defines a function which returns the sum of the cubes of all it's
  766. X    parameters.
  767. END_OF_FILE
  768. if test 2679 -ne `wc -c <'help/define'`; then
  769.     echo shar: \"'help/define'\" unpacked with wrong size!
  770. fi
  771. # end of 'help/define'
  772. fi
  773. if test -f 'help/mat' -a "${1}" != "-c" ; then 
  774.   echo shar: Will not clobber existing file \"'help/mat'\"
  775. else
  776. echo shar: Extracting \"'help/mat'\" \(4259 characters\)
  777. sed "s/^X//" >'help/mat' <<'END_OF_FILE'
  778. XUsing matrices
  779. X
  780. X    Matrices can have from 1 to 4 dimensions, and are indexed by a
  781. X    normal-sized integer.  The lower and upper bounds of a matrix can
  782. X    be specified at runtime.  The elements of a matrix are defaulted
  783. X    to zeroes, but can be assigned to be of any type.  Thus matrices
  784. X    can hold complex numbers, strings, objects, etc.  Matrices are
  785. X    stored in memory as an array so that random access to the elements
  786. X    is easy.
  787. X
  788. X    Matrices are normally indexed using square brackets.  If the matrix
  789. X    is multi-dimensional, then an element can be indexed either by
  790. X    using multiple pairs of square brackets (as in C), or else by
  791. X    separating the indexes by commas.  Thus the following two statements
  792. X    reference the same matrix element:
  793. X
  794. X        x = name[3][5];
  795. X        x = name[3,5];
  796. X
  797. X    The double-square bracket operator can be used on any matrix to
  798. X    make references to the elements easy and efficient.  This operator
  799. X    bypasses the normal indexing mechanism, and treats the array as if
  800. X    it was one-dimensional and with a lower bound of zero.  In this
  801. X    indexing mode, elements correspond to the normal indexing mode where
  802. X    the rightmost index increases most frequently.  For example, when
  803. X    using double-square bracket indexing on a two-dimensional matrix,
  804. X    increasing indexes will reference the matrix elements left to right,
  805. X    row by row.  Thus in the following example, 'x' and 'y' are copied
  806. X    from the same matrix element:
  807. X
  808. X        mat m[1:2, 1:3];
  809. X        x = m[2,1];
  810. X        y = m[[3]];
  811. X
  812. X    There are functions which return information about a matrix.
  813. X    The 'size' functions returns the total number of elements.
  814. X    The 'matdim', 'matmin', and 'matmax' functions return the number
  815. X    of dimensions of a matrix, and the lower and upper index bounds
  816. X    for a dimension of a matrix.  For square matrices, the 'det'
  817. X    function calculates the determinant of the matrix.
  818. X
  819. X    Some functions return matrices as their results.  These    functions
  820. X    do not affect the original matrix argument, but instead return
  821. X    new matrices.  For example, the 'mattrans' function returns the
  822. X    transpose of a matrix, and 'inverse' returns the inverse of a
  823. X    matrix.  So to invert a matrix called 'x', you could use:
  824. X
  825. X        x = inverse(x);
  826. X
  827. X    The 'matfill' function fills all elements of a matrix with the
  828. X    specified value, and optionally fills the diagonal elements of a
  829. X    square matrix with a different value.  For example:
  830. X
  831. X        matfill(x,1);
  832. X
  833. X    will fill any matrix with ones, and:
  834. X
  835. X        matfill(x, 0, 1);
  836. X
  837. X    will create an identity matrix out of any square matrix.  Note that
  838. X    unlike most matrix functions, this function does not return a matrix
  839. X    value, but manipulates the matrix argument itself.
  840. X
  841. X    Matrices can be multiplied by numbers, which multiplies each element
  842. X    by the number.  Matrices can also be negated, conjugated, shifted,
  843. X    rounded, truncated, fraction'ed, and modulo'ed.  Each of these
  844. X    operations is applied to each element.
  845. X
  846. X    Matrices can be added or multiplied together if the operation is
  847. X    legal.  Note that even if the dimensions of matrices are compatible,
  848. X    operations can still fail because of mismatched lower bounds.  The
  849. X    lower bounds of two matrices must either match, or else one of them
  850. X    must have a lower bound of zero.  Thus the following code:
  851. X
  852. X        mat x[3:3];
  853. X        mat y[4:4];
  854. X        z = x + y;
  855. X
  856. X    fails because the calculator does not have a way of knowing what
  857. X    the bounds should be on the resulting matrix.  If the bounds match,
  858. X    then the resulting matrix has the same bounds.  If exactly one of
  859. X    the lower bounds is zero, then the resulting matrix will have the
  860. X    nonzero lower bounds.  Thus means that the bounds of a matrix are
  861. X    preserved when operated on by matrices with lower bounds of zero.
  862. X    For example:
  863. X
  864. X        mat x[3:7];
  865. X        mat y[5];
  866. X        z = x + y;
  867. X
  868. X    will succeed and assign the variable 'z' a matrix whose
  869. X    bounds are 3-7.
  870. X
  871. X    Vectors are matrices of only a single dimension.  The 'dp' and 'cp'
  872. X    functions calculate the dot product and cross product of a vector
  873. X    (cross product is only defined for vectors of size 3).
  874. X
  875. X    Matrices can be searched for particular values by using the 'search'
  876. X    and 'rsearch' functions.  They return the element number of the
  877. X    found value (zero based), or null if the value does not exist in the
  878. X    matrix.  Using the element number in double-bracket indexing will
  879. X    then refer to the found element.
  880. END_OF_FILE
  881. if test 4259 -ne `wc -c <'help/mat'`; then
  882.     echo shar: \"'help/mat'\" unpacked with wrong size!
  883. fi
  884. # end of 'help/mat'
  885. fi
  886. if test -f 'help/types' -a "${1}" != "-c" ; then 
  887.   echo shar: Will not clobber existing file \"'help/types'\"
  888. else
  889. echo shar: Extracting \"'help/types'\" \(3769 characters\)
  890. sed "s/^X//" >'help/types' <<'END_OF_FILE'
  891. XBuiltin types
  892. X
  893. X    The calculator has the following built-in types.
  894. X
  895. X    null value
  896. X        This is the undefined value type.  The function 'null'
  897. X        returns this value.  Functions which do not explicitly
  898. X        return a value return this type.  If a function is called
  899. X        with fewer parameters than it is defined for, then the
  900. X        missing parameters have the null type.  Defining a
  901. X        new variable initializes it to the null type.  The null
  902. X        value is false if used in an IF test.
  903. X
  904. X    rational numbers
  905. X        This is the basic data type of the calculator.
  906. X        These are fractions whose numerators and denominators
  907. X        can be arbitrarily large.  The fractions are always
  908. X        in lowest terms.  Integers have a denominator of 1.
  909. X        The numerator of the number contains the sign, so that
  910. X        the denominator is always positive.  When a number is
  911. X        entered in floating point or exponential notation, it is
  912. X        immediately converted to the appropriate fractional value.
  913. X        Printing a value as a floating point or exponential value
  914. X        involves a conversion from the fractional representation.
  915. X
  916. X        Numbers are stored in binary format, so that in general,
  917. X        bit tests and shifts are quicker than multiplies and divides.
  918. X        Similarly, entering or displaying of numbers in binary,
  919. X        octal, or hex formats is quicker than in decimal.  The
  920. X        sign of a number does not affect the bit representation
  921. X        of a number.
  922. X
  923. X    complex numbers
  924. X        Complex numbers are composed of real and imaginary parts,
  925. X        which are both fractions as defined above.  An integer which
  926. X        is followed by an 'i' character is a pure imaginary number.
  927. X        Complex numbers such as "2+3i" when typed in, are processed
  928. X        as the sum of a real and pure imaginary number, resulting
  929. X        in the desired complex number.  Therefore, parenthesis are
  930. X        sometimes necessary to avoid confusion, as in the two values:
  931. X
  932. X            1+2i ^2        (which is -3)
  933. X            (1+2i) ^2    (which is -3+4i)
  934. X
  935. X        Similar care is required when entering fractional complex
  936. X        numbers.  Note the differences below:
  937. X
  938. X            3/4i        (which is -(3/4)i)
  939. X            3i/4        (which is (3/4)i)
  940. X
  941. X        The imaginary unit itself is input using "1i".
  942. X
  943. X    strings
  944. X        Strings are a sequence of zero or more characters.
  945. X        They are input using either of the single or double
  946. X        quote characters.  The quote mark which starts the
  947. X        string also ends it.  Various special characters can
  948. X        also be inserted using back-slash.  Example strings:
  949. X
  950. X            "hello\n"
  951. X            "that's all"
  952. X            'lots of """"'
  953. X            'a'
  954. X            ""
  955. X
  956. X        There is no distinction between single character and
  957. X        multi-character strings.  The 'str' and 'ord' functions
  958. X        will convert between a single character string and its
  959. X        numeric value.  The 'str' and 'eval' functions will
  960. X        convert between longer strings and the corresponding
  961. X        numeric value (if legal).  The 'strcat', 'strlen', and
  962. X        'substr' functions are also useful.
  963. X
  964. X    matrices
  965. X        These are one to four dimensional matrices, whose minimum
  966. X        and maximum bounds can be specified at runtime.  Unlike C,
  967. X        the minimum bounds of a matrix do not have to start at 0.
  968. X        The elements of a matrix can be of any type.  There are
  969. X        several built-in functions for matrices.  Matrices are
  970. X        created using the 'mat' statement.
  971. X
  972. X
  973. X    lists
  974. X        These are a sequence of values, which are linked together
  975. X        so that elements can be easily be inserted or removed
  976. X        anywhere in the list.  The values can be of any type.
  977. X        Lists are created using the 'list' function.
  978. X
  979. X    files
  980. X        These are text files opened using stdio.  Files may be opened
  981. X        for sequential reading, writing, or appending.  Opening a
  982. X        file using the 'fopen' function returns a value which can
  983. X        then be used to perform I/O to that file.  File values can
  984. X        be copied by normal assignments between variables, or by
  985. X        using the result of the 'files' function.  Such copies are
  986. X        indistinguishable from each other.
  987. END_OF_FILE
  988. if test 3769 -ne `wc -c <'help/types'`; then
  989.     echo shar: \"'help/types'\" unpacked with wrong size!
  990. fi
  991. # end of 'help/types'
  992. fi
  993. if test -f 'label.c' -a "${1}" != "-c" ; then 
  994.   echo shar: Will not clobber existing file \"'label.c'\"
  995. else
  996. echo shar: Extracting \"'label.c'\" \(3751 characters\)
  997. sed "s/^X//" >'label.c' <<'END_OF_FILE'
  998. X/*
  999. X * Copyright (c) 1992 David I. Bell
  1000. X * Permission is granted to use, distribute, or modify this source,
  1001. X * provided that this copyright notice remains intact.
  1002. X *
  1003. X * Label handling routines.
  1004. X */
  1005. X
  1006. X#include "calc.h"
  1007. X#include "token.h"
  1008. X#include "label.h"
  1009. X#include "string.h"
  1010. X#include "opcodes.h"
  1011. X#include "func.h"
  1012. X
  1013. Xstatic long labelcount;            /* number of user labels defined */
  1014. Xstatic STRINGHEAD labelnames;        /* list of user label names */
  1015. Xstatic LABEL labels[MAXLABELS];        /* list of user labels */
  1016. X
  1017. X
  1018. X/*
  1019. X * Initialize the table of labels for a function.
  1020. X */
  1021. Xvoid
  1022. Xinitlabels()
  1023. X{
  1024. X    labelcount = 0;
  1025. X    initstr(&labelnames);
  1026. X}
  1027. X
  1028. X
  1029. X/*
  1030. X * Define a user named label to have the offset of the next opcode.
  1031. X */
  1032. Xvoid
  1033. Xdefinelabel(name)
  1034. X    char *name;            /* label name */
  1035. X{
  1036. X    register LABEL *lp;        /* current label */
  1037. X    long i;                /* current label index */
  1038. X
  1039. X    i = findstr(&labelnames, name);
  1040. X    if (i >= 0) {
  1041. X        lp = &labels[i];
  1042. X        if (lp->l_offset) {
  1043. X            scanerror(T_NULL, "Label \"%s\" is multiply defined",
  1044. X                name);
  1045. X            return;
  1046. X        }
  1047. X        setlabel(lp);
  1048. X        return;
  1049. X    }
  1050. X    if (labelcount >= MAXLABELS) {
  1051. X        scanerror(T_NULL, "Too many labels in use");
  1052. X        return;
  1053. X    }
  1054. X    lp = &labels[labelcount++];
  1055. X    lp->l_chain = 0;
  1056. X    lp->l_offset = curfunc->f_opcodecount;
  1057. X    lp->l_name = addstr(&labelnames, name);
  1058. X    clearopt();
  1059. X}
  1060. X
  1061. X
  1062. X/*
  1063. X * Add the offset corresponding to the specified user label name to the
  1064. X * opcode table for a function. If the label is not yet defined, then a
  1065. X * chain of undefined offsets is built using the offset value, and it
  1066. X * will be fixed up when the label is defined.
  1067. X */
  1068. Xvoid
  1069. Xaddlabel(name)
  1070. X    char *name;            /* user symbol name */
  1071. X{
  1072. X    register LABEL *lp;        /* current label */
  1073. X    long i;                /* counter */
  1074. X
  1075. X    for (i = labelcount, lp = labels; --i >= 0; lp++) {
  1076. X        if (strcmp(name, lp->l_name))
  1077. X            continue;
  1078. X        uselabel(lp);
  1079. X        return;
  1080. X    }
  1081. X    if (labelcount >= MAXLABELS) {
  1082. X        scanerror(T_NULL, "Too many labels in use");
  1083. X        return;
  1084. X    }
  1085. X    lp = &labels[labelcount++];
  1086. X    lp->l_offset = 0;
  1087. X    lp->l_chain = curfunc->f_opcodecount;
  1088. X    lp->l_name = addstr(&labelnames, name);
  1089. X    addop(0);
  1090. X}
  1091. X
  1092. X
  1093. X/*
  1094. X * Check to make sure that all labels are defined.
  1095. X */
  1096. Xvoid
  1097. Xchecklabels()
  1098. X{
  1099. X    register LABEL *lp;        /* label being checked */
  1100. X    long i;                /* counter */
  1101. X
  1102. X    for (i = labelcount, lp = labels; --i >= 0; lp++) {
  1103. X        if (lp->l_offset > 0)
  1104. X            continue;
  1105. X        scanerror(T_NULL, "Label \"%s\" was never defined",
  1106. X            lp->l_name);
  1107. X    }
  1108. X}
  1109. X
  1110. X
  1111. X/*
  1112. X * Clear an internal label for use.
  1113. X */
  1114. Xvoid
  1115. Xclearlabel(lp)
  1116. X    register LABEL *lp;    /* label being cleared */
  1117. X{
  1118. X    lp->l_offset = 0;
  1119. X    lp->l_chain = 0;
  1120. X    lp->l_name = NULL;
  1121. X}
  1122. X
  1123. X
  1124. X/*
  1125. X * Set any label to have the value of the next opcode in the current
  1126. X * function being defined.  If there were forward references to it,
  1127. X * all such references are patched up.
  1128. X */
  1129. Xvoid
  1130. Xsetlabel(lp)
  1131. X    register LABEL *lp;    /* label being set */
  1132. X{
  1133. X    register FUNC *fp;    /* current function */
  1134. X    long curfix;        /* offset of current location being fixed */
  1135. X    long nextfix;        /* offset of next location to fix up */
  1136. X    long offset;        /* offset of this label */
  1137. X
  1138. X    fp = curfunc;
  1139. X    offset = fp->f_opcodecount;
  1140. X    nextfix = lp->l_chain;
  1141. X    while (nextfix > 0) {
  1142. X        curfix = nextfix;
  1143. X        nextfix = fp->f_opcodes[curfix];
  1144. X        fp->f_opcodes[curfix] = offset;
  1145. X    }
  1146. X    lp->l_chain = 0;
  1147. X    lp->l_offset = offset;
  1148. X    clearopt();
  1149. X}
  1150. X
  1151. X
  1152. X/*
  1153. X * Use the specified label at the current location in the function
  1154. X * being compiled.  This adds one word to the current function being
  1155. X * compiled.  If the label is not yet defined, a patch chain is built
  1156. X * so the reference can be fixed when the label is defined.
  1157. X */
  1158. Xvoid
  1159. Xuselabel(lp)
  1160. X    register LABEL *lp;        /* label being used */
  1161. X{
  1162. X    long offset;            /* offset being added */
  1163. X
  1164. X    offset = curfunc->f_opcodecount;
  1165. X    if (lp->l_offset > 0) {
  1166. X        addop(lp->l_offset);
  1167. X        return;
  1168. X    }
  1169. X    addop(lp->l_chain);
  1170. X    lp->l_chain = offset;
  1171. X}
  1172. X
  1173. X/* END CODE */
  1174. END_OF_FILE
  1175. if test 3751 -ne `wc -c <'label.c'`; then
  1176.     echo shar: \"'label.c'\" unpacked with wrong size!
  1177. fi
  1178. # end of 'label.c'
  1179. fi
  1180. if test -f 'lib/README' -a "${1}" != "-c" ; then 
  1181.   echo shar: Will not clobber existing file \"'lib/README'\"
  1182. else
  1183. echo shar: Extracting \"'lib/README'\" \(4595 characters\)
  1184. sed "s/^X//" >'lib/README' <<'END_OF_FILE'
  1185. X
  1186. X# Copyright (c) 1992 David I. Bell and Landon Curt Noll
  1187. X# Permission is granted to use, distribute, or modify this source,
  1188. X# provided that this copyright notice remains intact.
  1189. X
  1190. XThe following calc library files are provided because they serve as 
  1191. Xexamples of how use the calc language, and because the authors thought 
  1192. Xthem to be useful!
  1193. X
  1194. XIf you write something that you think is useful, please send it to:
  1195. X
  1196. X    dbell@pdact.pd.necisa.oz.au     {uunet,pyramid}!pdact.pd.necisa.oz.au!dbell
  1197. X    chongo@toad.com                 {uunet,pyramid,sun}!hoptoad!chongo
  1198. X
  1199. XBy convention, a lib file just defines functions, objects and variales.
  1200. X(The regression test is an exception.)  Also by convention, the a usage
  1201. Xmessage regarding each important object and function is printed at
  1202. Xthe time of the read.  This message printing may be disabled by assigning
  1203. Xthe global value  lib_debug  to a numeric value > 0.
  1204. X
  1205. X
  1206. Xbernoulli.cal
  1207. X
  1208. X    B(n)
  1209. X    Calculate the nth Bernoulli number.
  1210. X
  1211. X
  1212. Xbigprime.cal
  1213. X
  1214. X    bigprime(a, m, p) 
  1215. X
  1216. X    A prime test, base a, on p*2^x+1 for even x>m.
  1217. X
  1218. X
  1219. Xdeg.cal        
  1220. X
  1221. X    dms(deg, min, sec)
  1222. X    dms_add(a, b)
  1223. X    dms_neg(a)
  1224. X    dms_sub(a, b)
  1225. X    dms_mul(a, b)
  1226. X    dms_print(a)
  1227. X
  1228. X    Calculate in degrees, minutes, and seconds.
  1229. X
  1230. X
  1231. Xellip.cal    
  1232. X
  1233. X    factor(iN, ia, B, force)
  1234. X
  1235. X    Attempt to factor using the elliptic functions: y^2 = x^3 + a*x + b.
  1236. X
  1237. X
  1238. Xlucas.cal
  1239. X
  1240. X    lucas(h, n)
  1241. X
  1242. X    Perform a primality test of h*2^n-1, with 1<=h<2*n.
  1243. X
  1244. X
  1245. Xlucas_chk.cal
  1246. X
  1247. X    lucas_chk(high_n)
  1248. X
  1249. X    Test all primes of the form h*2^n-1, with 1<=h<200 and n <= high_n.
  1250. X    Requires lucas.cal to be loaded.  The highest useful high_n is 1000.
  1251. X
  1252. X
  1253. Xlucas_tbl.cal
  1254. X
  1255. X    Lucasian criteria for primality tables.
  1256. X
  1257. X
  1258. Xmersenne.cal
  1259. X
  1260. X    mersenne(p)
  1261. X
  1262. X    Perform a primality test of 2^p-1, for prime p>1.
  1263. X
  1264. X
  1265. Xmod.cal    
  1266. X
  1267. X    mod(a)
  1268. X    mod_print(a)
  1269. X    mod_one()
  1270. X    mod_cmp(a, b)
  1271. X    mod_rel(a, b)
  1272. X    mod_add(a, b)
  1273. X    mod_sub(a, b)
  1274. X    mod_neg(a)
  1275. X    mod_mul(a, b)
  1276. X    mod_square(a)
  1277. X    mod_inc(a)
  1278. X    mod_dec(a)
  1279. X    mod_inv(a)
  1280. X    mod_div(a, b)
  1281. X    mod_pow(a, b)
  1282. X
  1283. X    Routines to handle numbers modulo a specified number.
  1284. X
  1285. X
  1286. Xnextprim.cal
  1287. X
  1288. X    nextprime(n, tries)
  1289. X
  1290. X    Function to find the next prime (probably).
  1291. X
  1292. X
  1293. Xpell.cal
  1294. X
  1295. X    pellx(D)
  1296. X    pell(D)
  1297. X
  1298. X    Solve Pell's equation; Returns the solution X to: X^2 - D * Y^2 = 1.
  1299. X    Type the solution to pells equation for a particular D.
  1300. X
  1301. X
  1302. Xpi.cal
  1303. X
  1304. X    qpi(epsilon)
  1305. X
  1306. X    Calculate pi within the specified epsilon using the quartic convergence
  1307. X    iteration.
  1308. X
  1309. X
  1310. Xpollard.cal
  1311. X
  1312. X    factor(N, N, ai, af)
  1313. X
  1314. X    Factor using Pollard's p-1 method.
  1315. X
  1316. X
  1317. Xpoly.cal    
  1318. X
  1319. X    pol()
  1320. X    poly_print(a)
  1321. X    poly_add(a, b)
  1322. X    poly_neg(a)
  1323. X    poly_sub(a, b)
  1324. X    poly_mul(a, b)
  1325. X    poly_div(a, b)
  1326. X    ev(a, x)
  1327. X
  1328. X    Calculate with polynomials of one variable
  1329. X
  1330. X
  1331. Xpsqrt.cal    
  1332. X
  1333. X    psqrt(u, p)
  1334. X
  1335. X    Calculate square roots modulo a prime
  1336. X
  1337. X
  1338. Xquat.cal
  1339. X
  1340. X    quat(a, b, c, d)
  1341. X    quat_print(a)
  1342. X    quat_norm(a)
  1343. X    quat_abs(a, e)
  1344. X    quat_conj(a)
  1345. X    quat_add(a, b)
  1346. X    quat_sub(a, b)
  1347. X    quat_inc(a)
  1348. X    quat_dec(a)
  1349. X    quat_neg(a)
  1350. X    quat_mul(a, b)
  1351. X    quat_div(a, b)
  1352. X    quat_inv(a)
  1353. X    quat_scale(a, b)
  1354. X    quat_shift(a, b)
  1355. X
  1356. X    Calculate using quaternions of the form: a + bi + cj + dk.  In these
  1357. X    functions, quaternians are manipulated in the form: s + v, where
  1358. X    s is a scalar and v is a vector of size 3.
  1359. X
  1360. X
  1361. Xregress.cal    
  1362. X
  1363. X    Test the correct execution of the calculator by reading this library file.
  1364. X    Errors are reported with '****' mssages, or worse.  :-)
  1365. X
  1366. X
  1367. Xsolve.cal    
  1368. X
  1369. X    solve(low, high, epsilon)
  1370. X
  1371. X    Solve the equation f(x) = 0 to within the desired error value for x.
  1372. X    The function 'f' must be defined outside of this routine, and the low
  1373. X    and high values are guesses which must produce values with opposite signs.
  1374. X
  1375. X
  1376. Xsumsq.cal    
  1377. X
  1378. X    ss(p)
  1379. X
  1380. X    Determine the unique two positive integers whose squares sum to the
  1381. X    specified prime.  This is always possible for all primes of the form
  1382. X    4N+1, and always impossible for primes of the form 4N-1.
  1383. X
  1384. X
  1385. Xsurd.cal    
  1386. X
  1387. X    surd(a, b)
  1388. X    surd_print(a)
  1389. X    surd_conj(a)
  1390. X    surd_norm(a)
  1391. X    surd_value(a, xepsilon)
  1392. X    surd_add(a, b)
  1393. X    surd_sub(a, b)
  1394. X    surd_inc(a)
  1395. X    surd_dec(a)
  1396. X    surd_neg(a)
  1397. X    surd_mul(a, b)
  1398. X    surd_square(a)
  1399. X    surd_scale(a, b)
  1400. X    surd_shift(a, b)
  1401. X    surd_div(a, b)
  1402. X    surd_inv(a)
  1403. X    surd_sgn(a)
  1404. X    surd_cmp(a, b)
  1405. X    surd_rel(a, b)
  1406. X
  1407. X    Calculate using quadratic surds of the form: a + b * sqrt(D).
  1408. X
  1409. X
  1410. Xunitfrac.cal
  1411. X
  1412. X    unitfrac(x)
  1413. X
  1414. X    Represent a fraction as sum of distinct unit fractions.
  1415. X
  1416. X
  1417. Xvarargs.cal
  1418. X
  1419. X    sc(a, b, ...)
  1420. X
  1421. X    Example program to use 'varargs'.  Program to sum the cubes of all 
  1422. X    the specified numbers.
  1423. END_OF_FILE
  1424. if test 4595 -ne `wc -c <'lib/README'`; then
  1425.     echo shar: \"'lib/README'\" unpacked with wrong size!
  1426. fi
  1427. # end of 'lib/README'
  1428. fi
  1429. if test -f 'lib/mod.cal' -a "${1}" != "-c" ; then 
  1430.   echo shar: Will not clobber existing file \"'lib/mod.cal'\"
  1431. else
  1432. echo shar: Extracting \"'lib/mod.cal'\" \(3593 characters\)
  1433. sed "s/^X//" >'lib/mod.cal' <<'END_OF_FILE'
  1434. X/*
  1435. X * Copyright (c) 1992 David I. Bell
  1436. X * Permission is granted to use, distribute, or modify this source,
  1437. X * provided that this copyright notice remains intact.
  1438. X *
  1439. X * Routines to handle numbers modulo a specified number.
  1440. X *    a (mod N)
  1441. X */
  1442. X
  1443. Xobj mod {a};            /* definition of the object */
  1444. X
  1445. Xglobal mod_value;        /* modulus value (value of N) */
  1446. X
  1447. X
  1448. Xdefine mod(a)
  1449. X{
  1450. X    local x;
  1451. X
  1452. X    obj mod x;
  1453. X    if (!isreal(a) || !isint(a))
  1454. X        quit "Bad argument for mod function";
  1455. X    x.a = a % mod_value;
  1456. X    return x;
  1457. X}
  1458. X
  1459. X
  1460. Xdefine mod_print(a)
  1461. X{
  1462. X    if (digits(mod_value) <= 20)
  1463. X        print a.a, "(mod", mod_value : ")" :;
  1464. X    else
  1465. X        print a.a, "(mod N)" :;
  1466. X}
  1467. X
  1468. X
  1469. Xdefine mod_one()
  1470. X{
  1471. X    return mod(1);
  1472. X}
  1473. X
  1474. X
  1475. Xdefine mod_cmp(a, b)
  1476. X{
  1477. X    if (isnum(a))
  1478. X        return (a % mod_value) != b.a;
  1479. X    if (isnum(b))
  1480. X        return (b % mod_value) != a.a;
  1481. X    return a.a != b.a;
  1482. X}
  1483. X
  1484. X
  1485. Xdefine mod_rel(a, b)
  1486. X{
  1487. X    if (isnum(a))
  1488. X        a = mod(a);
  1489. X    if (isnum(b))
  1490. X        b = mod(b);
  1491. X    if (a.a < b.a)
  1492. X        return -1;
  1493. X    return a.a != b.a;
  1494. X}
  1495. X
  1496. X
  1497. Xdefine mod_add(a, b)
  1498. X{
  1499. X    local x;
  1500. X
  1501. X    obj mod x;
  1502. X    if (isnum(b)) {
  1503. X        if (!isint(b))
  1504. X            quit "Adding non-integer";
  1505. X        x.a = (a.a + b) % mod_value;
  1506. X        return x;
  1507. X    }
  1508. X    if (isnum(a)) {
  1509. X        if (!isint(a))
  1510. X            quit "Adding non-integer";
  1511. X        x.a = (a + b.a) % mod_value;
  1512. X        return x;
  1513. X    }
  1514. X    x.a = (a.a + b.a) % mod_value;
  1515. X    return x;
  1516. X}
  1517. X
  1518. X
  1519. Xdefine mod_sub(a, b)
  1520. X{
  1521. X    return a + (-b);
  1522. X}
  1523. X
  1524. X
  1525. Xdefine mod_neg(a)
  1526. X{
  1527. X    local x;
  1528. X
  1529. X    obj mod x;
  1530. X    x.a = mod_value - a.a;
  1531. X    return x;
  1532. X}
  1533. X
  1534. X
  1535. Xdefine mod_mul(a, b)
  1536. X{
  1537. X    local x;
  1538. X
  1539. X    obj mod x;
  1540. X    if (isnum(b)) {
  1541. X        if (!isint(b))
  1542. X            quit "Multiplying by non-integer";
  1543. X        x.a = (a.a * b) % mod_value;
  1544. X        return x;
  1545. X    }
  1546. X    if (isnum(a)) {
  1547. X        if (!isint(a))
  1548. X            quit "Multiplying by non-integer";
  1549. X        x.a = (a * b.a) % mod_value;
  1550. X        return x;
  1551. X    }
  1552. X    x.a = (a.a * b.a) % mod_value;
  1553. X    return x;
  1554. X}
  1555. X
  1556. X
  1557. Xdefine mod_square(a)
  1558. X{
  1559. X    local x;
  1560. X
  1561. X    obj mod x;
  1562. X    x.a = a.a^2 % mod_value;
  1563. X    return x;
  1564. X}
  1565. X
  1566. X
  1567. Xdefine mod_inc(a)
  1568. X{
  1569. X    local x;
  1570. X
  1571. X    x = a;
  1572. X    if (++x.a == mod_value)
  1573. X        x.a = 0;
  1574. X    return x;
  1575. X}
  1576. X
  1577. X
  1578. Xdefine mod_dec(a)
  1579. X{
  1580. X    local x;
  1581. X
  1582. X    x = a;
  1583. X    if (--x.a < 0)
  1584. X        x.a = mod_value - 1;
  1585. X    return x;
  1586. X}
  1587. X
  1588. X
  1589. Xdefine mod_inv(a)
  1590. X{
  1591. X    local x;
  1592. X
  1593. X    obj mod x;
  1594. X    x.a = minv(a.a, mod_value);
  1595. X    return x;
  1596. X}
  1597. X
  1598. X
  1599. Xdefine mod_div(a, b)
  1600. X{
  1601. X    local c, x, y;
  1602. X
  1603. X    obj mod x, y;
  1604. X    if (isnum(a))
  1605. X        a = mod(a);
  1606. X    if (isnum(b))
  1607. X        b = mod(b);
  1608. X    c = gcd(a.a, b.a);
  1609. X    x.a = a.a / c;
  1610. X    y.a = b.a / c;
  1611. X    return x * inverse(y);
  1612. X}
  1613. X
  1614. X
  1615. Xdefine mod_pow(a, b)
  1616. X{
  1617. X    local x, y, z;
  1618. X
  1619. X    obj mod x;
  1620. X    y = a;
  1621. X    z = b;
  1622. X    if (b < 0) {
  1623. X        y = inverse(a);
  1624. X        z = -b;
  1625. X    }
  1626. X    x.a = pmod(y.a, z, mod_value);
  1627. X    return x;
  1628. X}
  1629. X
  1630. X
  1631. Xmod_value = 100;        /* default */
  1632. X
  1633. Xglobal lib_debug;
  1634. Xif (!isnum(lib_debug) || lib_debug>0) print "obj mod {a} defined"
  1635. Xif (!isnum(lib_debug) || lib_debug>0) print "mod(a) defined"
  1636. Xif (!isnum(lib_debug) || lib_debug>0) print "mod_print(a) defined"
  1637. Xif (!isnum(lib_debug) || lib_debug>0) print "mod_one(a) defined"
  1638. Xif (!isnum(lib_debug) || lib_debug>0) print "mod_cmp(a, b) defined"
  1639. Xif (!isnum(lib_debug) || lib_debug>0) print "mod_rel(a, b) defined"
  1640. Xif (!isnum(lib_debug) || lib_debug>0) print "mod_add(a, b) defined"
  1641. Xif (!isnum(lib_debug) || lib_debug>0) print "mod_sub(a, b) defined"
  1642. Xif (!isnum(lib_debug) || lib_debug>0) print "mod_mod(a, b) defined"
  1643. Xif (!isnum(lib_debug) || lib_debug>0) print "mod_square(a) defined"
  1644. Xif (!isnum(lib_debug) || lib_debug>0) print "mod_inc(a) defined"
  1645. Xif (!isnum(lib_debug) || lib_debug>0) print "mod_dec(a) defined"
  1646. Xif (!isnum(lib_debug) || lib_debug>0) print "mod_inv(a) defined"
  1647. Xif (!isnum(lib_debug) || lib_debug>0) print "mod_div(a, b) defined"
  1648. Xif (!isnum(lib_debug) || lib_debug>0) print "mod_pow(a, b) defined"
  1649. Xif (!isnum(lib_debug) || lib_debug>0) print "mod_value defined"
  1650. Xif (!isnum(lib_debug) || lib_debug>0) print "set mod_value as needed"
  1651. END_OF_FILE
  1652. if test 3593 -ne `wc -c <'lib/mod.cal'`; then
  1653.     echo shar: \"'lib/mod.cal'\" unpacked with wrong size!
  1654. fi
  1655. # end of 'lib/mod.cal'
  1656. fi
  1657. if test -f 'lib/poly.cal' -a "${1}" != "-c" ; then 
  1658.   echo shar: Will not clobber existing file \"'lib/poly.cal'\"
  1659. else
  1660. echo shar: Extracting \"'lib/poly.cal'\" \(3619 characters\)
  1661. sed "s/^X//" >'lib/poly.cal' <<'END_OF_FILE'
  1662. X/*
  1663. X * Copyright (c) 1992 David I. Bell
  1664. X * Permission is granted to use, distribute, or modify this source,
  1665. X * provided that this copyright notice remains intact.
  1666. X *
  1667. X * Calculate with polynomials of one variable.
  1668. X */
  1669. X
  1670. Xobj poly {deg, coef};
  1671. X
  1672. X
  1673. Xdefine pol()
  1674. X{
  1675. X    local x, d, i;
  1676. X
  1677. X    d = param(0) - 1;
  1678. X    if (d < 0)
  1679. X        quit "No coefficients for pol";
  1680. X    if (d == 0)
  1681. X        return param(1);
  1682. X    obj poly x;
  1683. X    x.deg = d;
  1684. X    mat x.coef[d+1];
  1685. X    for (i = 0; i <= d; i++)
  1686. X        x.coef[d-i] = param(i+1);
  1687. X    return x;
  1688. X}
  1689. X
  1690. X
  1691. Xdefine poly_print(a)
  1692. X{
  1693. X    local i, n;
  1694. X
  1695. X    for (i = a.deg; i >= 0; i--) {
  1696. X        n = a.coef[i];
  1697. X        if (n == 0)
  1698. X            continue;
  1699. X        if (i == a.deg) {
  1700. X            if (isreal(n) && (n < 0)) {
  1701. X                print "- " : ;
  1702. X                n = abs(n);
  1703. X            }
  1704. X        } else {
  1705. X            if (!isreal(n) || (n > 0))
  1706. X                print " + " : ;
  1707. X            else {
  1708. X                print " - " : ;
  1709. X                n = abs(n);
  1710. X            }
  1711. X        }
  1712. X        if ((n != 1) && (i > 0)) {
  1713. X            if (isreal(n))
  1714. X                print n : "*" : ;
  1715. X            else
  1716. X                print "(" : n : ")*" : ;
  1717. X        }
  1718. X        switch (i) {
  1719. X            case 0:
  1720. X                if (isreal(n))
  1721. X                    print n : ;
  1722. X                else
  1723. X                    print "(" : n : ")" : ;
  1724. X                break;
  1725. X            case 1:
  1726. X                print "X" : ;
  1727. X                break;
  1728. X            default:
  1729. X                print "X^" : i : ;
  1730. X        }
  1731. X    }
  1732. X}
  1733. X
  1734. X
  1735. Xdefine poly_add(a, b)
  1736. X{
  1737. X    local x, d;
  1738. X
  1739. X    if (isnum(b)) {
  1740. X        x = a;
  1741. X        x.coef[0] += b;
  1742. X        return x;
  1743. X    }
  1744. X    if (isnum(a)) {
  1745. X        x = b;
  1746. X        x.coef[0] += a;
  1747. X        return x;
  1748. X    }
  1749. X    if (a.deg == b.deg) {
  1750. X        d = a.deg;
  1751. X        while (a.coef[d] == -b.coef[d])
  1752. X            if (--d <= 0)
  1753. X                return a.coef[0] + b.coef[0];
  1754. X    }
  1755. X    d = max(a.deg, b.deg);
  1756. X    obj poly x;
  1757. X    x.deg = d;
  1758. X    mat x.coef[d+1];
  1759. X    while (d >= 0) {
  1760. X        if (d > a.deg)
  1761. X            x.coef[d] = b.coef[d];
  1762. X        else if (d > b.deg)
  1763. X            x.coef[d] = a.coef[d];
  1764. X        else
  1765. X            x.coef[d] = a.coef[d] + b.coef[d];
  1766. X        d--;
  1767. X    }
  1768. X    return x;
  1769. X}
  1770. X
  1771. X
  1772. Xdefine poly_neg(a)
  1773. X{
  1774. X    local x, i;
  1775. X
  1776. X    x = a;
  1777. X    for (i = x.deg; i >= 0; i--)
  1778. X        x.coef[i] = -x.coef[i];
  1779. X    return x;
  1780. X}
  1781. X
  1782. X
  1783. Xdefine poly_sub(a, b)
  1784. X{
  1785. X    return a + (-b);
  1786. X}
  1787. X
  1788. X
  1789. Xdefine poly_mul(a, b)
  1790. X{
  1791. X    local x, i, j;
  1792. X
  1793. X    if (isnum(b)) {
  1794. X        if (b == 0)
  1795. X            return 0;
  1796. X        if (b == 1)
  1797. X            return a;
  1798. X        if (b == -1)
  1799. X            return -a;
  1800. X        x = a;
  1801. X        for (i = x.deg; i >= 0; i--)
  1802. X            x.coef[i] *= b;
  1803. X        return x;
  1804. X    }
  1805. X    if (isnum(a)) {
  1806. X        if (a == 0)
  1807. X            return 0;
  1808. X        if (a == 1)
  1809. X            return a;
  1810. X        if (a == -1)
  1811. X            return -a;
  1812. X        x = b;
  1813. X        for (i = x.deg; i >= 0; i--)
  1814. X            x.coef[i] *= a;
  1815. X        return x;
  1816. X    }
  1817. X    obj poly x;
  1818. X    x.deg = a.deg + b.deg;
  1819. X    mat x.coef[x.deg+1];
  1820. X    for (i = a.deg; i >= 0; i--)
  1821. X        for (j = b.deg; j >= 0; j--)
  1822. X            x.coef[i+j] += a.coef[i] * b.coef[j];
  1823. X    return x;
  1824. X}
  1825. X
  1826. X
  1827. Xdefine poly_div(a, b)
  1828. X{
  1829. X    local i, x;
  1830. X
  1831. X    if (!isnum(b))
  1832. X        quit "Only division by numbers currently allowed";
  1833. X    if (b == 0)
  1834. X        quit "Division by zero";
  1835. X    if (b == 1)
  1836. X        return a;
  1837. X    if (b == -1)
  1838. X        return -a;
  1839. X    x = a;
  1840. X    for (i = x.deg; i >= 0; i--)
  1841. X        x.coef[i] /= b;
  1842. X    return x;
  1843. X}
  1844. X
  1845. X
  1846. Xdefine ev(a, x)
  1847. X{
  1848. X    local i, r;
  1849. X
  1850. X    obj poly r;
  1851. X    if (!istype(a, r))
  1852. X        quit "Evaluating non-polynomial";
  1853. X    i = a.deg;
  1854. X    r = a.coef[i];
  1855. X    while (--i >= 0)
  1856. X        r = r * x + a.coef[i];
  1857. X    return r;
  1858. X}
  1859. X
  1860. Xglobal lib_debug;
  1861. Xif (!isnum(lib_debug) || lib_debug>0) print "obj poly {deg, coef} defined"
  1862. Xif (!isnum(lib_debug) || lib_debug>0) print "pol() defined"
  1863. Xif (!isnum(lib_debug) || lib_debug>0) print "poly_print(a) defined"
  1864. Xif (!isnum(lib_debug) || lib_debug>0) print "poly_add(a, b) defined"
  1865. Xif (!isnum(lib_debug) || lib_debug>0) print "poly_neg(a) defined"
  1866. Xif (!isnum(lib_debug) || lib_debug>0) print "poly_sub(a, b) defined"
  1867. Xif (!isnum(lib_debug) || lib_debug>0) print "poly_mul(a, b) defined"
  1868. Xif (!isnum(lib_debug) || lib_debug>0) print "poly_div(a, b) defined"
  1869. Xif (!isnum(lib_debug) || lib_debug>0) print "ev(a, x) defined"
  1870. Xif (!isnum(lib_debug) || lib_debug>0) print "Use pol() to make polynomials (high coefficient first)"
  1871. Xif (!isnum(lib_debug) || lib_debug>0) print "Use ev(a, x) to evaluate them"
  1872. END_OF_FILE
  1873. if test 3619 -ne `wc -c <'lib/poly.cal'`; then
  1874.     echo shar: \"'lib/poly.cal'\" unpacked with wrong size!
  1875. fi
  1876. # end of 'lib/poly.cal'
  1877. fi
  1878. if test -f 'lib/quat.cal' -a "${1}" != "-c" ; then 
  1879.   echo shar: Will not clobber existing file \"'lib/quat.cal'\"
  1880. else
  1881. echo shar: Extracting \"'lib/quat.cal'\" \(3577 characters\)
  1882. sed "s/^X//" >'lib/quat.cal' <<'END_OF_FILE'
  1883. X/*
  1884. X * Copyright (c) 1992 David I. Bell
  1885. X * Permission is granted to use, distribute, or modify this source,
  1886. X * provided that this copyright notice remains intact.
  1887. X *
  1888. X * Routines to handle quaternions of the form:
  1889. X *    a + bi + cj + dk
  1890. X *
  1891. X * Note: In this module, quaternians are manipulated in the form:
  1892. X *    s + v
  1893. X * Where s is a scalar and v is a vector of size 3.
  1894. X */
  1895. X
  1896. Xobj quat {s, v};        /* definition of the quaternion object */
  1897. X
  1898. X
  1899. Xdefine quat(a,b,c,d)
  1900. X{
  1901. X    local x;
  1902. X
  1903. X    obj quat x;
  1904. X    x.s = isnull(a) ? 0 : a;
  1905. X    mat x.v[3];
  1906. X    x.v[0] = isnull(b) ? 0 : b;
  1907. X    x.v[1] = isnull(c) ? 0 : c;
  1908. X    x.v[2] = isnull(d) ? 0 : d;
  1909. X    return x;
  1910. X}
  1911. X
  1912. X
  1913. Xdefine quat_print(a)
  1914. X{
  1915. X    print "quat(" : a.s : ", " : a.v[0] : ", " : a.v[1] : ", " : a.v[2] : ")" :;
  1916. X}
  1917. X
  1918. X
  1919. Xdefine quat_norm(a)
  1920. X{
  1921. X    return a.s^2 + dp(a.v, a.v);
  1922. X}
  1923. X
  1924. X
  1925. Xdefine quat_abs(a, e)
  1926. X{
  1927. X    return sqrt(a.s^2 + dp(a.v, a.v), e);
  1928. X}
  1929. X
  1930. X
  1931. Xdefine quat_conj(a)
  1932. X{
  1933. X    local    x;
  1934. X
  1935. X    obj quat x;
  1936. X    x.s = a.s;
  1937. X    x.v = -a.v;
  1938. X    return x;
  1939. X}
  1940. X
  1941. X
  1942. Xdefine quat_add(a, b)
  1943. X{
  1944. X    local x;
  1945. X
  1946. X    obj quat x;
  1947. X    if (!istype(b, x)) {
  1948. X        x.s = a.s + b;
  1949. X        x.v = a.v;
  1950. X        return x;
  1951. X    }
  1952. X    if (!istype(a, x)) {
  1953. X        x.s = a + b.s;
  1954. X        x.v = b.v;
  1955. X        return x;
  1956. X    }
  1957. X    x.s = a.s + b.s;
  1958. X    x.v = a.v + b.v;
  1959. X    if (x.v)
  1960. X        return x;
  1961. X    return x.s;
  1962. X}
  1963. X
  1964. X
  1965. Xdefine quat_sub(a, b)
  1966. X{
  1967. X    local x;
  1968. X
  1969. X    obj quat x;
  1970. X    if (!istype(b, x)) {
  1971. X        x.s = a.s - b;
  1972. X        x.v = a.v;
  1973. X        return x;
  1974. X    }
  1975. X    if (!istype(a, x)) {
  1976. X        x.s = a - b.s;
  1977. X        x.v = -b.v;
  1978. X        return x;
  1979. X    }
  1980. X    x.s = a.s - b.s;
  1981. X    x.v = a.v - b.v;
  1982. X    if (x.v)
  1983. X        return x;
  1984. X    return x.s;
  1985. X}
  1986. X
  1987. X
  1988. Xdefine quat_inc(a)
  1989. X{
  1990. X    local    x;
  1991. X
  1992. X    x = a;
  1993. X    x.s++;
  1994. X    return x;
  1995. X}
  1996. X
  1997. X
  1998. Xdefine quat_dec(a)
  1999. X{
  2000. X    local    x;
  2001. X
  2002. X    x = a;
  2003. X    x.s--;
  2004. X    return x;
  2005. X}
  2006. X
  2007. X
  2008. Xdefine quat_neg(a)
  2009. X{
  2010. X    local    x;
  2011. X
  2012. X    obj quat x;
  2013. X    x.s = -a.s;
  2014. X    x.v = -a.v;
  2015. X    return x;
  2016. X}
  2017. X
  2018. X
  2019. Xdefine quat_mul(a, b)
  2020. X{
  2021. X    local x;
  2022. X
  2023. X    obj quat x;
  2024. X    if (!istype(b, x)) {
  2025. X        x.s = a.s * b;
  2026. X        x.v = a.v * b;
  2027. X    } else if (!istype(a, x)) {
  2028. X        x.s = b.s * a;
  2029. X        x.v = b.v * a;
  2030. X    } else {
  2031. X        x.s = a.s * b.s - dp(a.v, b.v);
  2032. X        x.v = a.s * b.v + b.s * a.v + cp(a.v, b.v);
  2033. X    }
  2034. X    if (x.v)
  2035. X        return x;
  2036. X    return x.s;
  2037. X}
  2038. X
  2039. X
  2040. Xdefine quat_div(a, b)
  2041. X{
  2042. X    local    x;
  2043. X
  2044. X    obj quat x;
  2045. X    if (!istype(b, x)) {
  2046. X        x.s = a.s / b;
  2047. X        x.v = a.v / b;
  2048. X        return x;
  2049. X    }
  2050. X    return a * quat_inv(b);
  2051. X}
  2052. X
  2053. X
  2054. Xdefine quat_inv(a)
  2055. X{
  2056. X    local    x, q2;
  2057. X
  2058. X    obj quat x;
  2059. X    q2 = a.s^2 + dp(a.v, a.v);
  2060. X    x.s = a.s / q2;
  2061. X    x.v = a.v / (-q2);
  2062. X    return x;
  2063. X}
  2064. X
  2065. X
  2066. Xdefine quat_scale(a, b)
  2067. X{
  2068. X    local    x;
  2069. X
  2070. X    obj quat x;
  2071. X    x.s = scale(a.s, b);
  2072. X    x.v = scale(a.v, b);
  2073. X    return x;
  2074. X}
  2075. X
  2076. X
  2077. Xdefine quat_shift(a, b)
  2078. X{
  2079. X    local    x;
  2080. X
  2081. X    obj quat x;
  2082. X    x.s = a.s << b;
  2083. X    x.v = a.v << b;
  2084. X    if (x.v)
  2085. X        return x;
  2086. X    return x.s;
  2087. X}
  2088. X
  2089. Xglobal lib_debug;
  2090. Xif (!isnum(lib_debug) || lib_debug>0) print "obj quat {s, v} defined"
  2091. Xif (!isnum(lib_debug) || lib_debug>0) print "quat(a, b, c, d) defined"
  2092. Xif (!isnum(lib_debug) || lib_debug>0) print "quat_print(a) defined"
  2093. Xif (!isnum(lib_debug) || lib_debug>0) print "quat_norm(a) defined"
  2094. Xif (!isnum(lib_debug) || lib_debug>0) print "quat_abs(a, e) defined"
  2095. Xif (!isnum(lib_debug) || lib_debug>0) print "quat_conj(a) defined"
  2096. Xif (!isnum(lib_debug) || lib_debug>0) print "quat_add(a, e) defined"
  2097. Xif (!isnum(lib_debug) || lib_debug>0) print "quat_sub(a, e) defined"
  2098. Xif (!isnum(lib_debug) || lib_debug>0) print "quat_inc(a) defined"
  2099. Xif (!isnum(lib_debug) || lib_debug>0) print "quat_dec(a) defined"
  2100. Xif (!isnum(lib_debug) || lib_debug>0) print "quat_neg(a) defined"
  2101. Xif (!isnum(lib_debug) || lib_debug>0) print "quat_mul(a, b) defined"
  2102. Xif (!isnum(lib_debug) || lib_debug>0) print "quat_div(a, b) defined"
  2103. Xif (!isnum(lib_debug) || lib_debug>0) print "quat_inv(a) defined"
  2104. Xif (!isnum(lib_debug) || lib_debug>0) print "quat_scale(a, b) defined"
  2105. Xif (!isnum(lib_debug) || lib_debug>0) print "quat_shift(a, b) defined"
  2106. END_OF_FILE
  2107. if test 3577 -ne `wc -c <'lib/quat.cal'`; then
  2108.     echo shar: \"'lib/quat.cal'\" unpacked with wrong size!
  2109. fi
  2110. # end of 'lib/quat.cal'
  2111. fi
  2112. echo shar: End of archive 2 \(of 21\).
  2113. cp /dev/null ark2isdone
  2114. MISSING=""
  2115. 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
  2116.     if test ! -f ark${I}isdone ; then
  2117.     MISSING="${MISSING} ${I}"
  2118.     fi
  2119. done
  2120. if test "${MISSING}" = "" ; then
  2121.     echo You have unpacked all 21 archives.
  2122.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2123. else
  2124.     echo You still need to unpack the following archives:
  2125.     echo "        " ${MISSING}
  2126. fi
  2127. ##  End of shell archive.
  2128. exit 0
  2129.