home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff274.lzh / HP11 / ins.c < prev    next >
C/C++ Source or Header  |  1989-11-16  |  20KB  |  1,215 lines

  1. #include "exec/types.h"
  2. #include "proto/dos.h"
  3.  
  4. #include "math.h"
  5. #include "string.h"
  6. #include "stdio.h"
  7.  
  8. #include "hp11/amiga/amiga.h"
  9. #include "hp11/hp11.h"
  10. #include "hp11/io.h"
  11. #include "hp11/support.h"
  12. #include "hp11/ins.h"
  13. #include "hp11/codes.h"
  14.  
  15. #define FOREVER() for(;;)
  16.  
  17. /* Declare the modules variables */
  18. BOOL enabled, entering, overflow;
  19.  
  20. BOOL expo, decpt;
  21. char strx[13], expx[4];
  22.  
  23. /* Function addresses */
  24. HP11Function insfunc[KCOMPLEX] =
  25. {
  26.    Sqrt,
  27.    Exp,
  28.    Exp10,
  29.    ExpYX,
  30.    Invert,
  31.    DoCHS,
  32.    Divide,
  33.    SIN,
  34.    COS,
  35.    TAN,
  36.    DoEEX,
  37.    Times,
  38.    RunStart,
  39.    Rdn,
  40.    ExgXY,
  41.    ENTER,
  42.    Minus,
  43.    DoPoint,
  44.    SigmaPlus,
  45.    Plus,
  46.  
  47.    Pi,
  48.    XleY,
  49.    ExgXInd,
  50.    ToRect,
  51.    ExgXI,
  52.    DSE,
  53.    ISG,
  54.    XgtY,
  55.    PSE,
  56.    ClearSigma,
  57.    ClearReg,
  58.    Random,
  59.    DoPerm,
  60.    ToHMS,
  61.    ToRAD,
  62.    XneY,
  63.    FRAC,
  64.    Fact,
  65.    Estimate,
  66.    LinearRegression,
  67.    XeqY,
  68.  
  69.    Sqr,
  70.    LN,
  71.    LOG,
  72.    Percent,
  73.    DeltaPercent,
  74.    ABS,
  75.    DEG,
  76.    RAD,
  77.    GRAD,
  78.    Xlt0,
  79.    ArcSIN,
  80.    ArcCOS,
  81.    ArcTAN,
  82.    ToPolar,
  83.    Xgt0,
  84.    RTN,
  85.    Rup,
  86.    RND,
  87.    CLX,
  88.    LSTX,
  89.    DoComb,
  90.    ToH,
  91.    ToDEG,
  92.    Xne0,
  93.    INT,
  94.    Mean,
  95.    SDev,
  96.    SigmaSub,
  97.    Xeq0,
  98.  
  99.    STORandom,
  100.    RCLSigma,
  101.  
  102.    HypSIN,
  103.    HypCOS,
  104.    HypTAN,
  105.  
  106.    ArcHypSIN,
  107.    ArcHypCOS,
  108.    ArcHypTAN
  109. };
  110.  
  111. /* Various functions used to conserve code space. Could be macros or simply
  112.   instructions */
  113. void DISABLE() { enabled = FALSE; entering = FALSE; }
  114.  
  115. void ENABLE() { enabled = TRUE; entering = FALSE; }
  116.  
  117. void LisX(void)
  118. {
  119.    L = X;
  120. }
  121.  
  122. void XisY(void)
  123. {
  124.    X = Y;
  125. }
  126.  
  127. void YisX(void)
  128. {
  129.    Y = X;
  130. }
  131.  
  132. void YisZ(void)
  133. {
  134.    Y = Z;
  135. }
  136.  
  137. void ZisY(void)
  138. {
  139.    Z = Y;
  140. }
  141.  
  142. void ZisT(void)
  143. {
  144.    Z = T;
  145. }
  146.  
  147. void TisZ(void)
  148. {
  149.    T = Z;
  150. }
  151.  
  152. /* Check r against HP11 limits */
  153. double Check(r)
  154. double r;
  155. {
  156.    if (fabs(r) > MAXHP11) {
  157.       r = MAXHP11 * sign(r);
  158.       overflow = TRUE; /* Overflow has occured */
  159.    }
  160.    else if (fabs(r) < MINHP11) r = 0.0;
  161.  
  162.    return(r);
  163. }
  164.  
  165. void Drop(void) /* Drop stack & save X in L */
  166. {
  167.    ENABLE();
  168.    LisX(); XisY(); YisZ(); ZisT();
  169. /* L = X(); X = Y; Y = Z; Z = T; */
  170. }
  171.  
  172. void Enter(void) /* Move stack up */
  173. {
  174.    TisZ(); ZisY(); YisX();
  175. /* T = Z; Z = Y; Y = X; */
  176. }
  177.  
  178. void Lift(void) /* lift stack if enabled, ENABLE stack */
  179. {
  180.    if (enabled) Enter();
  181.    ENABLE();
  182. }
  183.  
  184. void SaveX(void) /* Frequent: L = X; ENABLE(); (most simple instructions eg sin do this) */
  185. {
  186.    LisX();
  187.    ENABLE();
  188. }
  189.  
  190. /* Convert x from current trig setting to radians */
  191. double from(double x)
  192. {
  193.    switch (Angles) {
  194.       case deg:return(FDEG(x));
  195.       case rad:return(x);
  196.       case grad:return(FGRAD(x));
  197.    }
  198. }
  199.  
  200. /* Convert radian value to current trig setting */
  201. double toa(double x)
  202. {
  203.    switch (Angles) {
  204.       case deg:return(TDEG(x));
  205.       case rad:return(x);
  206.       case grad:return(TGRAD(x));
  207.    }
  208. }
  209.  
  210. /* Used by statistical formulae (terminology from HP11 doc) */
  211. double M(void) { return(R[0] * R[2] - R[1] * R[1]); }
  212. #define N() (R[0] * R[4] - R[3] * R[3]) /* used only once */
  213. double P(void) { return(R[0] * R[5] - R[1] * R[3]); }
  214.  
  215. double *Reg(int n) /* Return address of register n */
  216. {
  217.    if (n == OI) return(&I);
  218.    else if (n == OIND_R) /* indirection */
  219.       if (I >= 0.0 && I < 20.0) return(R + (int)I);
  220.       else return(NULL); /* Unknown reg */
  221.    else return(R + n);
  222. }
  223.  
  224. /* Convert current input value to real, return false if fails (no exponent) */
  225. void StdVal(void)
  226. {
  227.    X = atof(strx);
  228. }
  229.  
  230. /* Convert current input value to real, return false if fails (exponent) */
  231. void ExpoVal(void)
  232. {
  233.    char buf[80];
  234.  
  235.    /* buf = strx + "E" + expx, with leading blanks stripped from expx */
  236.    strcat(strcat(strcpy(buf,strx),"E"), stpblk(expx));
  237.  
  238.    X = atof(buf);
  239. }
  240.  
  241. /* Act on key to modify current input value */
  242. void EnterNum(key)
  243. register int key;
  244. {
  245.    register int lens;
  246.  
  247.    if (!entering) { /* No current digit entry */
  248.       if (enabled) Enter(); /* lift stack ? */
  249.       entering = enabled = TRUE; /* stack enabled, number being entered */
  250.       expo = decpt = FALSE; /* No dec point or exponent */
  251.       strx[0] = ' '; strx[1] = '\0'; /* nb string empty (leading space for sign) */
  252.    }
  253.  
  254.    lens = strlen(strx); /* Current string length */
  255.    if (key >= KFIG + 0 && key <= KFIG + 9) /* Add digit */
  256.       if (expo) { /* to exponent */
  257.      expx[1] = expx[2]; expx[2] = key - KFIG + '0';
  258.       }
  259.       else {
  260.      strx[lens] = key - KFIG + '0'; strx[lens + 1] = '\0';
  261.      strx[scrpos(strx, 11) + 1] = '\0'; /* Cut string at end of hp11 screen pos
  262.         ==> prevent display overflow */
  263.       }
  264.    else
  265.       switch (key) {
  266.      case -IBACK: /* back-arrow, actions are passed as negative numbers to
  267.         distinguish them from instructions */
  268.         if (expo) /* Correct exponent */
  269.            if (strcmp(expx, "-00") == 0) strcpy(expx, " 00");
  270.            else if (strcmp(expx, " 00") == 0) expo = FALSE; /* delete exponent */
  271.            else {
  272.           expx[2] = expx[1]; expx[1] = '0';
  273.            }
  274.         else /* no exponent */
  275.            if (lens == 2) { CLX(); return; } /* end of digit entry,
  276.           must not evaluate current entry ==> exit */
  277.            else {
  278.           if (strx[lens - 1] == '.') decpt = FALSE;
  279.           strx[lens - 1] = '\0'; /* cut last char from str by moving eos mark */
  280.            }
  281.         break;
  282.      case KCHS:
  283.         if (expo) { /* change exponent sign */
  284.            expx[0] = (expx[0] == '-') ? ' ' : '-';
  285.         }
  286.         else { /* change number sign */
  287.            strx[0] = (strx[0] == '-') ? ' ' : '-';
  288.         }
  289.         break;
  290.      case KPOINT:
  291.         if (!expo && !decpt) {
  292.            decpt = TRUE;
  293.  
  294.            if (lens == 1) { strcpy(strx, " 0"); lens = 2; } /* if no digit entered, add a 0 */
  295.            strx[lens] = '.'; strx[lens + 1] = '\0';
  296.            strx[scrpos(strx, 11) + 1] = '\0';
  297.         }
  298.         break;
  299.      case KEEX:
  300.         if (!expo) {
  301.            expo = TRUE;
  302.            strcpy(expx, " 00");
  303.            if (lens == 1) strcpy(strx, " 1"); /* if no digit entered, add a 1 */
  304.         }
  305.       }
  306.    if (expo) ExpoVal();
  307.    else StdVal();
  308. }
  309.  
  310. void ExpYX() /* y^x */
  311. {
  312.    double t;
  313.  
  314.    errno = 0; /* set return code to 0 */
  315.    t = pow(Y, X);
  316.    if (errno != 0) Error('0'); /* Check math library return code */
  317.    else {
  318.       Y = t;
  319.       Drop();
  320.    }
  321. }
  322.  
  323. void CHS(void)
  324. {
  325.    ENABLE();
  326.    X = -X;
  327. }
  328.  
  329. void DoCHS()
  330. {
  331.    if (entering) EnterNum(KCHS);
  332.    else CHS();
  333. }
  334.  
  335. void DoEEX()
  336. {
  337.    EnterNum(KEEX);
  338. }
  339.  
  340. void DoPoint()
  341. {
  342.    EnterNum(KPOINT);
  343. }
  344.  
  345. void Rdn()
  346. {
  347.    double t;
  348.  
  349.    ENABLE();
  350.    t = X; XisY(); YisZ(); ZisT(); T = t;
  351. /* t = X; X = Y; Y = Z; Z = T; T = t; */
  352. }
  353.  
  354. void ExgXY() /* Exchange X & Y */
  355. {
  356.    double t;
  357.  
  358.    ENABLE();
  359.    t = X; XisY(); Y = t;
  360. /* t = X; X = Y; Y = t; */
  361. }
  362.  
  363. void ClearReg()
  364. {
  365.    int i;
  366.  
  367.    NEUTRAL();
  368.    for (i = 0; i < 20; i++) R[i] = 0.0;
  369.    I = 0;
  370. }
  371.  
  372. void Estimate() /* Statistics: estimate y from given x */
  373. {
  374.    double tm = M(), tr, ty, tp = P(); /* temporary results */
  375.  
  376.    tr = tm * N();
  377.    ty = R[0] * tm;
  378.  
  379.    if (tr < 0.0 || ty == 0.0) Error('2'); /* Stat error */
  380.    else {
  381.       Enter(); /* always lifts stack */
  382.       SaveX();
  383.  
  384.       X = (tm * R[3] + tp * (R[0] * X - R[1])) / ty; /* estimate */
  385.       Y = tp / sqrt(tr); /* Correlation coefficient */
  386.    }
  387. }
  388.  
  389. void LinearRegression()
  390. {
  391.    double tm = M(), tp = P();
  392.  
  393.    if (tm == 0.0 || R[0] == 0.0) Error('2');
  394.    else {
  395.       Lift(); /* Lift stack twice */
  396.       Enter();
  397.  
  398.       Y = tp / tm;
  399.       X = (tm * R[3] - tp * R[1]) / (R[0] * tm);
  400.    }
  401. }
  402.  
  403. void Rup()
  404. {
  405.    double t;
  406.  
  407.    ENABLE();
  408.    t = T; TisZ(); ZisY(); YisX(); X = t;
  409. /* t = T; T = Z; Z = Y; Y = X; X = t; */
  410. }
  411.  
  412. void SDev()
  413. {
  414.    double tx, ty, td;
  415.  
  416.    td = R[0] * (R[0] - 1.0);
  417.  
  418.    if (td == 0.0) Error('2');
  419.    else {
  420.       tx = M() / td;
  421.       ty = N() / td;
  422.  
  423.       if (tx < 0.0 || ty < 0.0) Error('2');
  424.       else {
  425.      Lift();
  426.      Enter();
  427.  
  428.      X = sqrt(tx); Y = sqrt(ty);
  429.       }
  430.    }
  431. }
  432.  
  433. void FIX(n)
  434. int n;
  435. {
  436.    NEUTRAL();
  437.    Mode = fix; Digits = n;
  438.    minfix = pow(10.0, (double)-Digits);
  439. }
  440.  
  441. void SCI(n)
  442. int n;
  443. {
  444.    NEUTRAL();
  445.    Mode = sci; Digits = n;
  446. }
  447.  
  448. void ENG(n)
  449. int n;
  450. {
  451.    NEUTRAL();
  452.    Mode = eng; Digits = n;
  453. }
  454.  
  455. void ExgXI() /* Exchange X with I */
  456. {
  457.    double t;
  458.  
  459.    ENABLE();
  460.    t = I; I = X; X = t;
  461. }
  462.  
  463. void ExgXInd() /* Exchange X with (i) */
  464. {
  465.    double t, *ptr;
  466.  
  467.    if (!(ptr = Reg(OIND_R))) Error('3'); /* get address of pointed register if exists */
  468.    else {
  469.       ENABLE();
  470.       t = *ptr; *ptr = X; X = t;
  471.    }
  472. }
  473.  
  474. void STO(n, type)
  475. int n;
  476. enum StoTypes type;
  477. {
  478.    double val;
  479.    register double *ptr;
  480.  
  481.    if (ptr = Reg(n)) { /* Valid register */
  482.  
  483.       switch (type) {
  484.      case sto: val = X; break;
  485.      case add: val = *ptr + X; break;
  486.      case sub: val = *ptr - X; break;
  487.      case mul: val = *ptr * X; break;
  488.      case div: if (X == 0.0) {
  489.               Error('0');
  490.               return; /* exit if error */
  491.            }
  492.            else val = *ptr / X; break;
  493.       }
  494.  
  495.       if (fabs(val) > MAXHP11) Error('1'); /* Register overflow */
  496.       else {
  497.      *ptr = val;
  498.      ENABLE();
  499.       }
  500.    }
  501.    else Error('3');
  502. }
  503.  
  504. void RCL(n)
  505. int n;
  506. {
  507.    double *ptr;
  508.  
  509.    if (ptr = Reg(n)) {
  510.       Lift();
  511.       X = *ptr;
  512.    }
  513.    else Error('3');
  514. }
  515.  
  516. void GTOLine(n) /* move to line n */
  517. int n;
  518. {
  519.    if (n >= 0 && n <= lastIns) PC = n;
  520.    else Error('4');
  521. }
  522.  
  523. void ProgramEntry() /* Enter a program */
  524. {
  525.    register int i;
  526.    WORD code;
  527.    register int inprog = TRUE;
  528.  
  529.    RelKey();
  530.  
  531.    ENABLE();
  532.  
  533.    do {
  534.       DisplayLine(); DispPRGM(TRUE); /* Program display */
  535.  
  536.       switch (ReadKey(&code)) {
  537.      case Instruction: /* Save it */
  538.         if (lastIns == MAXPROG) Error('4'); /* Memory full */
  539.         else {
  540.            for (i = lastIns; i > PC; i--) Prog[i + 1] = Prog[i]; /* Move program up */
  541.            lastIns++;
  542.            Prog[++PC] = code; /* store instruction */
  543.            retCnt = 0; /* Empty return stack */
  544.         };
  545.         break;
  546.      case Action: /* Act on it */
  547.         if (code >= IGTO_LINE) GTOLine(code - IGTO_LINE);
  548.         else switch (code) {
  549.            case ION: on = inprog = !RelKey(); break; /* Allow user to change his mind */
  550.            case IP_R: case IRESET: inprog = FALSE; break; /* exit program mode */
  551.            case IMEM: MEM(); break;
  552.            case IBACK: /* delete line */
  553.           if (PC != 0) {
  554.              for (i = PC; i < lastIns; i++) Prog[i] = Prog[i + 1]; /* del line */
  555.              lastIns--;
  556.              PC--;
  557.              retCnt = 0; /* empty stack when prog changed */
  558.           }
  559.           break;
  560.            case ISST: if (PC++ == lastIns) PC = 0; break;
  561.            case IBST: if (PC-- == 0) PC = lastIns; break;
  562.            case IUSER: USER(); break;
  563.            case ICLR_PRGM: lastIns = PC = 0; break;
  564.         }
  565.         break;
  566.       }
  567.       RelKey();
  568.    } while (inprog);
  569. }
  570.  
  571. void GTOLBL(int n)
  572. {
  573.    register int i;
  574.  
  575.    if (n > 14) Error('4');
  576.    else { /* Do a circular search from current line */
  577.       for (i = PC + 1; i <= lastIns; i++) /* Search from current line */
  578.      if (Prog[i] == KLBL + n) {
  579.         PC = i; return; /* found, exit */
  580.      }
  581.       for (i = 1; i < PC; i++) /* If that fails, search from start */
  582.      if (Prog[i] == KLBL + n) {
  583.         PC = i; return;
  584.      }
  585.       Error('4');
  586.    }
  587. }
  588.  
  589. void GTO(n)
  590. int n;
  591. {
  592.    if (n == OIND_G) /* Indirection */
  593.       if (I >= 0.0) GTOLBL((int)I); /* gto label if I >= 0 */
  594.       else GTOLine(-(int)I); /* gto line -I if i < 0 */
  595.    else GTOLBL(n);
  596.    if (!error) { /* success */
  597.       ENABLE();
  598.       if (running) PC--; /* Execute label instruction (even though useless),
  599.      must decrement PC in run mode because incremented after end ins */
  600.       else retCnt = 0; /* in normal mode, GTO clears return stack */
  601.    }
  602. }
  603.  
  604. void BreakupI(int *limit, int *step) /* From I deduce loop limit & step.
  605.  I is stored as nnnnn.lllss with nnnnn as the loop count, lll the limit &
  606.  ss the step. If ss == 0, the step is taken as 1 */
  607. {
  608.    double t;
  609.  
  610.    t = frac(I) * 1000.0;
  611.    *limit = (int)t;
  612.    *step = (int)(100.0 * (t - *limit));
  613.    if (*step == 0) *step = 1;
  614. }
  615.  
  616. void DSE()
  617. {
  618.    int limit, step;
  619.  
  620.    ENABLE();
  621.    BreakupI(&limit, &step);
  622.    I -= step;
  623.  
  624.    skip = (I <= limit);
  625. }
  626.  
  627. void ISG()
  628. {
  629.    int limit, step;
  630.  
  631.    ENABLE();
  632.    BreakupI(&limit, &step);
  633.    I += step;
  634.  
  635.    skip = (I > limit);
  636. }
  637.  
  638. void SF(n)
  639. int n;
  640. {
  641.    ENABLE();
  642.    Flags |= (1 << n);
  643. }
  644.  
  645. void CF(n)
  646. int n;
  647. {
  648.    ENABLE();
  649.    Flags &= ~(1 << n);
  650. }
  651.  
  652. void Set(n) /* Is flag n set ? */
  653. int n;
  654. {
  655.    ENABLE();
  656.    skip = !(Flags & (1 << n));
  657. }
  658.  
  659. void PSE()
  660. {
  661.    BOOL oldrun = running;
  662.  
  663.    NEUTRAL();
  664.    running = FALSE;
  665.    Disp();
  666.    Wait50(50);
  667.    running = oldrun;
  668. }
  669.  
  670. void RTN()
  671. {
  672.    ENABLE();
  673.    if (!running || retCnt == 0) { /* In normal mode RTN sets PC to 0 &
  674.       clears the return stack. In run mode, if the stack is empty, it also
  675.       sets PC to 0 & then it interrupts the program */
  676.       running = FALSE;
  677.       PC = 0; retCnt = 0;
  678.    }
  679.    else /* Return from subroutine */
  680.       PC = retStack[--retCnt];
  681. }
  682.  
  683. void GSB(n)
  684. int n;
  685. {
  686.    if (retCnt == MAXSTACK) Error('5'); /* Stack full */
  687.    else {
  688.       if (running) {
  689.      retStack[retCnt++] = PC; /* Save PC */
  690.      GTO(n); /* Jump to prog line */
  691.      if (error) retCnt--; /* If this fails, reclaim stack space */
  692.       }
  693.       else { /* in normal mode, GSB = GTO + R/S */
  694.      retCnt = 0;
  695.      GTO(n);
  696.      running = !error;
  697.       }
  698.    }
  699. }
  700.  
  701. void HP11ColdReset() /* ColdReset HP11 (Menu option: New) */
  702. {
  703.    Display("  Pr Error");
  704.  
  705.    DEG();
  706.    FIX(4);
  707.    PC = lastIns = 0;
  708.    running = User = comma = FALSE;
  709.    Flags = retCnt = 0;
  710.    ClearSigma(); L = 0.0;
  711.    ClearReg();
  712.  
  713.    GetKey();
  714. }
  715.  
  716. void MEM() /* Display available memory */
  717. {
  718.    char mem[20];
  719.  
  720.    NEUTRAL();
  721.    sprintf(mem, " P-%-4dr- .9", MAXPROG - lastIns);
  722.    /* There are always all the register hence the r- .9, %-4d left justifies the number
  723.      of lines in a 4 character field */
  724.    Display(mem);
  725.    RelKey();
  726. }
  727.  
  728. void PREFIX() /* Display digits of number in x */
  729. {
  730.    char *disp, buf[20];
  731.    int dec, sign;
  732.  
  733.    NEUTRAL();
  734.  
  735.    if (X != 0.0) {
  736.       disp = ecvt(X, 10, &dec, &sign); /* The ideal library function for this */
  737.       buf[0] = ' '; strcpy(buf + 1, disp);
  738.       Display(buf);
  739.    }
  740.    else Display(" 0000000000");
  741.  
  742.    RelKey();
  743. }
  744.  
  745. void RND()
  746. {
  747.    double fx, tx;
  748.    char buf[20];
  749.  
  750.    SaveX();
  751.  
  752.    switch (Mode) {
  753.       case fix:
  754.      fx = modf(X, &tx);
  755.      X = tx + trunc(fx / minfix + 0.5) * minfix;
  756.      break;
  757.       case sci: case eng:
  758.      sprintf(buf, "%0.*e", Digits, X);
  759.      X = atof(buf);
  760.      break;
  761.    }
  762. }
  763.  
  764. void Sqrt()
  765. {
  766.    if (X < 0.0) Error('0');
  767.    else {
  768.       SaveX(); X = sqrt(X);
  769.    }
  770. }
  771.  
  772. void Exp() /* e^x */
  773. {
  774.    SaveX(); X = exp(X);
  775. }
  776.  
  777. void Exp10() /* 10^x */
  778. {
  779.    SaveX(); X = pow(10.0, X);
  780. }
  781.  
  782. void Invert() /* 1/x */
  783. {
  784.    if (X == 0.0) Error('0');
  785.    else {
  786.       SaveX(); X = 1.0 / X;
  787.    }
  788. }
  789.  
  790. void Divide()
  791. {
  792.    if (X == 0.0) Error('0');
  793.    else {
  794.       Y = Y / X;
  795.       Drop();
  796.    }
  797. }
  798.  
  799. void SIN()
  800. {
  801.    SaveX(); X = sin(from(X));
  802. }
  803.  
  804. void COS()
  805. {
  806.    SaveX(); X = cos(from(X));
  807. }
  808.  
  809. void TAN()
  810. {
  811.    SaveX(); X = tan(from(X));
  812. }
  813.  
  814. void Times()
  815. {
  816.    Y = Y * X;
  817.    Drop();
  818. }
  819.  
  820. void ENTER()
  821. {
  822.    DISABLE();
  823.    Enter();
  824. }
  825.  
  826. void Minus()
  827. {
  828.    Y = Y - X;
  829.    Drop();
  830. }
  831.  
  832. void SigmaPlus() /* Accumulate statistics */
  833. {
  834.    R[0] += 1.0;
  835.    R[1] = Check(R[1] + X);
  836.    R[2] = Check(R[2] + X * X);
  837.    R[3] = Check(R[3] + Y);
  838.    R[4] = Check(R[4] + Y * Y);
  839.    R[5] = Check(R[5] + X * Y);
  840.  
  841.    DISABLE();
  842.    LisX(); X = R[0];
  843. }
  844.  
  845. void Plus()
  846. {
  847.    Y = Y + X;
  848.    Drop();
  849. }
  850.  
  851. void Pi()
  852. {
  853.    Lift();
  854.    X = PI;
  855. }
  856.  
  857.  
  858. void ToRect()
  859. {
  860.    SaveX();
  861.    Rect(X, from(Y), &X, &Y);
  862. }
  863.  
  864. void ClearSigma() /* Clear statistics */
  865. {
  866.    NEUTRAL(); /* Doesn't really matter, could be anything (but the HP11 doc says
  867.       neutral so it will be neutral ... */
  868.    X = Y = Z = T = R[0] = R[1] = R[2] = R[3] = R[4] = R[5] = 0.0;
  869. }
  870.  
  871. void Random() /* Random number generator. This isn't the same as the HP11 one, for I
  872.    don't know what the HP11 uses. */
  873. {
  874.    Lift();
  875.    X = drand48();
  876. }
  877.  
  878. void DoPerm() /* P y,x */
  879. {
  880.    if (X <= Y && X > 0.0) {
  881.       Y = Perm((int)Y, (int)X);
  882.       Drop();
  883.    }
  884.    else Error('0');
  885. }
  886.  
  887. void ToHMS()
  888. {
  889.    SaveX(); X = hms(X);
  890. }
  891.  
  892. void ToRAD()
  893. {
  894.    SaveX(); X = FDEG(X);
  895. }
  896.  
  897. void FRAC()
  898. {
  899.    SaveX(); X = frac(X);
  900. }
  901.  
  902. void Fact() /* gamma/factorial function */
  903. {
  904.    SaveX();
  905.    if (X > MAXFACT) X = MAXHP11;
  906.    else if (X >= 0 && X == trunc(X)) X = factorial((int)X);
  907.    else X = gamma(1.0 + X);
  908. }
  909.  
  910. void Sqr()
  911. {
  912.    SaveX(); X = X * X;
  913. }
  914.  
  915. void LN()
  916. {
  917.    if (X <= 0.0) Error('0');
  918.    else {
  919.       SaveX(); X = log(X);
  920.    }
  921. }
  922.  
  923. void LOG()
  924. {
  925.    if (X <= 0.0) Error('0');
  926.    else {
  927.       SaveX(); X = log10(X);
  928.    }
  929. }
  930.  
  931. void Percent()
  932. {
  933.    /* doesn't drop stack */
  934.    SaveX(); X = X * Y / 100.0;
  935. }
  936.  
  937. void DeltaPercent() /* Percentage of difference between x & y */
  938. {
  939.    if (Y == 0.0) Error('0');
  940.    else {
  941.       SaveX(); X = 100.0 * (X - Y) / Y;
  942.    }
  943. }
  944.  
  945. void ABS()
  946. {
  947.    SaveX(); X = fabs(X);
  948. }
  949.  
  950.  
  951. void DEG()
  952. {
  953.    NEUTRAL();
  954.    Angles = deg;
  955. }
  956.  
  957. void RAD()
  958. {
  959.    NEUTRAL();
  960.    Angles = rad;
  961. }
  962.  
  963. void GRAD()
  964. {
  965.    NEUTRAL();
  966.    Angles = grad;
  967. }
  968.  
  969. void ArcSIN()
  970. {
  971.    if (fabs(X) > 1.0) Error('0');
  972.    else {
  973.       SaveX(); X = toa(asin(X));
  974.    }
  975. }
  976.  
  977. void ArcCOS()
  978. {
  979.    if (fabs(X) > 1.0) Error('0');
  980.    else {
  981.       SaveX(); X = toa(acos(X));
  982.    }
  983. }
  984.  
  985. void ArcTAN()
  986. {
  987.    SaveX(); X = toa(atan(X));
  988. }
  989.  
  990. void ToPolar()
  991. {
  992.    SaveX();
  993.    Polar(X, Y, &X, &Y);
  994.    Y = toa(Y);
  995. }
  996.  
  997. void CLX()
  998. {
  999.    X = 0.0;
  1000.    DISABLE();
  1001. }
  1002.  
  1003. void LSTX()
  1004. {
  1005.    Lift();
  1006.    X = L;
  1007. }
  1008.  
  1009. void DoComb() /* C y,x */
  1010. {
  1011.    if (X <= Y && X > 0.0) {
  1012.       Y = Comb((int)Y, (int)X);
  1013.       Drop();
  1014.    }
  1015.    else Error('0');
  1016. }
  1017.  
  1018. void ToH()
  1019. {
  1020.    SaveX(); X = hr(X);
  1021. }
  1022.  
  1023. void ToDEG()
  1024. {
  1025.    SaveX(); X = TDEG(X);
  1026. }
  1027.  
  1028. void INT()
  1029. {
  1030.    SaveX(); X = trunc(X);
  1031. }
  1032.  
  1033. void Mean()
  1034. {
  1035.    if (R[0] == 0.0) Error('2');
  1036.    else {
  1037.       Lift();
  1038.       Enter();
  1039.  
  1040.       X = R[1] / R[0];
  1041.       Y = R[3] / R[0];
  1042.    }
  1043. }
  1044.  
  1045. void SigmaSub() /* Correct error in statistics accumulation */
  1046. {
  1047.    R[0] -= 1.0;
  1048.    R[1] = Check(R[1] - X);
  1049.    R[2] = Check(R[2] - X * X);
  1050.    R[3] = Check(R[3] - Y);
  1051.    R[4] = Check(R[4] - Y * Y);
  1052.    R[5] = Check(R[5] - X * Y);
  1053.  
  1054.    DISABLE();
  1055.    LisX(); X = R[0];
  1056. }
  1057.  
  1058. void HypSIN()
  1059. {
  1060.    SaveX(); X = sinh(X);
  1061. }
  1062.  
  1063. void HypCOS()
  1064. {
  1065.    SaveX(); X = cosh(X);
  1066. }
  1067.  
  1068. void HypTAN()
  1069. {
  1070.    SaveX(); X = tanh(X);
  1071. }
  1072.  
  1073. void ArcHypSIN()
  1074. {
  1075.    SaveX(); X = asinh(X);
  1076. }
  1077.  
  1078. void ArcHypCOS()
  1079. {
  1080.    if (fabs(X) < 1.0) Error('0');
  1081.    else {
  1082.       SaveX(); X = acosh(X);
  1083.    }
  1084. }
  1085.  
  1086. void ArcHypTAN()
  1087. {
  1088.    if (fabs(X) > 1.0) Error('0');
  1089.    else {
  1090.       SaveX(); X = atanh(X);
  1091.    }
  1092. }
  1093.  
  1094. void STORandom() /* Set random generator seed */
  1095. {
  1096.    ENABLE();
  1097.    srand48((long)X);
  1098.    /* Use integer part of seed, something better could be used */
  1099. }
  1100.  
  1101. void RCLSigma() /* Recall accumulated x & y totals */
  1102. {
  1103.    Lift();
  1104.    Enter();
  1105.  
  1106.    X = R[1]; Y = R[3];
  1107. }
  1108.  
  1109. void USER() /* Toggle user mode */
  1110. {
  1111.    NEUTRAL();
  1112.    User = !User;
  1113. }
  1114.  
  1115. void RunStart() /* Should be called RunStop ! */
  1116. {
  1117.    NEUTRAL();
  1118.    if (running) running = FALSE; /* Stop */
  1119.    else { /* Run */
  1120.       if (lastIns != 0) { /* if a program to run */
  1121.      running = TRUE;
  1122.      if (PC == 0) PC = 1; /* skip first line */
  1123.       }
  1124.  
  1125.       DisplayLine(); /* Display first line */
  1126.       RelKey();
  1127.    }
  1128. }
  1129.  
  1130. void XleY()
  1131. {
  1132.    ENABLE();
  1133.    skip = (X > Y); /* skip if condition fails */
  1134. }
  1135.  
  1136. void Xlt0()
  1137. {
  1138.    ENABLE();
  1139.    skip = (X >= 0.0);
  1140. }
  1141.  
  1142. void XgtY()
  1143. {
  1144.    ENABLE();
  1145.    skip = (X <= Y);
  1146. }
  1147.  
  1148. void Xgt0()
  1149. {
  1150.    ENABLE();
  1151.    skip = (X <= 0.0);
  1152. }
  1153.  
  1154. void XneY()
  1155. {
  1156.    ENABLE();
  1157.    skip = (X == Y);
  1158. }
  1159.  
  1160. void Xne0()
  1161. {
  1162.    ENABLE();
  1163.    skip = (X == 0.0);
  1164. }
  1165.  
  1166. void XeqY()
  1167. {
  1168.    ENABLE();
  1169.    skip = (X != Y);
  1170. }
  1171.  
  1172. void Xeq0()
  1173. {
  1174.    ENABLE();
  1175.    skip = (X != 0.0);
  1176. }
  1177.  
  1178. void SST() /* Single step a program */
  1179. {
  1180.    if (lastIns == 0) { /* No program to single step through */
  1181.       DisplayLine();
  1182.       RelKey();
  1183.    }
  1184.    else {
  1185.       if (PC == 0) PC = 1; /* skip line 0 */
  1186.  
  1187.       DisplayLine();
  1188.       RelKey();
  1189.  
  1190.       running = TRUE; /* Pretend line is being run */
  1191.       ExecIns(Prog[PC]); /* Exec ins */
  1192.       if (!error && !overflow) { /* idem main loop */
  1193.      if (skip) PC++;
  1194.      PC++;
  1195.      while (PC > lastIns) {
  1196.         RTN();
  1197.         PC++;
  1198.      }
  1199.       }
  1200.       running = FALSE;
  1201.  
  1202.    }
  1203. }
  1204.  
  1205. void BST() /* move back one line (but don't correct its effect) */
  1206. {
  1207.    if (PC == 0) PC = lastIns;
  1208.    else PC--;
  1209.  
  1210.    DisplayLine();
  1211.    RelKey();
  1212. }
  1213.  
  1214.  
  1215.