home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / cpm / calculat / calc224.lbr / CALC_E.IZC / CALC_E.INC
Text File  |  1987-07-19  |  10KB  |  406 lines

  1. function fix_post(expr : str; var post_expr : str) : boolean;
  2. var
  3.    valid : boolean;
  4.    token : str;
  5. begin { procedure fix_post }
  6.    valid := true;
  7.    post_expr := '';
  8.    while get_token(expr, token) do
  9.       begin
  10.       post_expr := post_expr + token + ' ';
  11.       end;
  12.    fix_post := valid;
  13. end; { function fix_post }
  14.  
  15. function eval_post(expr : str; var val : number) : boolean;
  16. type
  17.    num_ptr = ^num_rec;
  18.    num_rec = record
  19.                 num  : str;
  20.                 next : num_ptr;
  21.              end;
  22. var
  23.    num_stack : num_ptr;
  24.    result    : str;
  25.    token     : str;
  26.    valid     : boolean;
  27.  
  28. function empty(num_stack : num_ptr) : boolean;
  29. begin { function empty }
  30.    empty := num_stack = nil;
  31. end; { function empty }
  32.  
  33. function pop(var num_stack : num_ptr) : str;
  34. var
  35.    prev : num_ptr;
  36. begin { function pop }
  37.    if empty(num_stack) then
  38.       begin
  39.       pop := '';
  40.       writeln('Stack empty.');
  41.       end
  42.    else
  43.       begin
  44.       pop      := num_stack^.num;
  45.       prev     := num_stack;
  46.       num_stack := num_stack^.next;
  47.       dispose(prev);
  48.       end;
  49. end; { function pop }
  50.  
  51. procedure push(var num_stack : num_ptr; num : str);
  52. var
  53.    new_num : num_ptr;
  54. begin { procedure push }
  55.    new(new_num);
  56.    new_num^.num   := num;
  57.    new_num^.next := num_stack;
  58.    num_stack     := new_num;
  59. end; { procdure push }
  60.  
  61. function top(num_stack : num_ptr) : str;
  62. begin { function top }
  63.    if empty(num_stack) then
  64.       begin
  65.       top := '';
  66.       writeln('Stack empty.');
  67.       end
  68.    else
  69.       top := num_stack^.num;
  70. end; { function top }
  71.  
  72. function get_token(var s : str; var token : str) : boolean;
  73. begin { function get_token }
  74.    if s = '' then
  75.       get_token := false
  76.    else
  77.       begin
  78.       token := copy(s, 1, pos(' ', s) - 1);
  79.       s := copy(s, pos(' ', s) + 1, length(s) - pos(' ', s));
  80.       get_token := true;
  81.       end;
  82. end; { function get_token }
  83.  
  84.  
  85.  
  86.  
  87. procedure add(num1, num2 : number; var result : number); forward;
  88.  
  89. procedure sub(num1, num2 : number; var result : number);
  90.  
  91. procedure sub_sub(num1, num2 : number; var result : number);
  92. var
  93.    temp   : integer;
  94.    borrow : integer;
  95.    b      : integer;
  96. begin { procedure sub_sub }
  97.    borrow := 0;
  98.    for b := 1 to MAXB do
  99.       begin
  100.       temp := (num1.n[b] - borrow) - num2.n[b];
  101.       if (temp < 0) then
  102.          begin
  103.          result.n[b] := temp + 256;
  104.          borrow := 1;
  105.          end
  106.       else
  107.          begin
  108.          result.n[b] := temp;
  109.          borrow := 0;
  110.          end;
  111.       end;
  112.    if (borrow <> 0) then
  113.       writeln('sub_sub: incorrect subtraction.');
  114. end; { procedure sub_sub }
  115.  
  116. begin { procedure sub }
  117.    if num1.s * num2.s = -1 then
  118.       begin
  119.       num2.s   := - num2.s;
  120.       add(num1, num2, result);
  121.       result.s := num1.s;
  122.       end
  123.    else
  124.       if (numcmp(num1, num2) >= 0) then
  125.          begin
  126.          sub_sub(num1, num2, result);
  127.          result.s := num1.s;
  128.          end
  129.       else
  130.          begin
  131.          sub_sub(num2, num1, result);
  132.          result.s := - num1.s;
  133.          end;
  134. end; { procedure sub }
  135.  
  136. procedure add {num1, num2 : number; var result : number} ;
  137.  
  138. procedure add_add(num1, num2 : number; var result : number);
  139. var
  140.    b,
  141.    carry : integer;
  142. begin { procedure add_add }
  143.    carry := 0;
  144.    for b := 1 to MAXB do
  145.       begin
  146.       result.n[b] := (num1.n[b] + num2.n[b] + carry) mod 256;
  147.       carry       := (num1.n[b] + num2.n[b] + carry) div 256;
  148.       end;
  149.    if (carry > 0) then
  150.       writeln('numeric overflow.');
  151. end; { procedure add_add }
  152.  
  153. begin { procedure add }
  154.    if num1.s * num2.s = -1 then
  155.       if num1.s = -1 then
  156.          begin
  157.          num1.s := 1;
  158.          sub(num2, num1, result);
  159.          end
  160.       else
  161.          begin
  162.          num2.s := 1;
  163.          sub(num1, num2, result);
  164.          end
  165.    else
  166.       begin
  167.       add_add(num1, num2, result);
  168.       result.s := num1.s;
  169.       end;
  170. end; { procedure add }
  171.  
  172. procedure mul(num1, num2 : number; var result : number);
  173. var
  174.    b        : integer;
  175.    i        : integer;
  176.    m_result : number;
  177. begin { procedure mul }
  178.    zero(result);
  179.    for b := 1 to MAXB do
  180.       begin
  181.       mult_ni(num1, num2.n[b], m_result);
  182.       for i := MAXB downto 1 do
  183.          begin
  184.          if i >= b then
  185.             m_result.n[i] := m_result.n[i - b + 1]
  186.          else
  187.             m_result.n[i] := 0;
  188.          end;
  189.       add(result, m_result, result);
  190.       end;
  191.    result.s := num1.s * num2.s;
  192. end; { procedure mul }
  193.  
  194. procedure dvd(num1, num2 : number; var result, remainder : number);
  195. var
  196.    b        : integer;
  197.    partial,
  198.    part_res : number;
  199.  
  200. procedure dvd_dvd(num1, num2 : number; var result, remainder : number);
  201. var
  202.    b : integer;
  203. begin { procedure dvd_dvd }
  204.    zero(result);
  205.    while (numcmp(num1, num2) >= 0) do
  206.       begin
  207.       sub(num1, num2, num1);
  208.       add_ni(result, 1, result);
  209.       end;
  210.    remainder.n := num1.n;
  211. end; { procedure dvd_dvd }
  212.  
  213. begin { procedure dvd }
  214.    zero(remainder);
  215.    for b := MAXB downto 1 do
  216.       begin
  217.       partial := remainder;
  218.       mult_ni(partial, 256, partial);
  219.       partial.n[1] := num1.n[b];
  220.       dvd_dvd(partial, num2, part_res, remainder);
  221.       result.n[b] := part_res.n[1];
  222.       end;
  223.  
  224.    result.s    := num1.s * num2.s;
  225.    remainder.s := 1;
  226. end; { procedure dvd }
  227.  
  228.  
  229. procedure pow(num1, num2 : number; var result : number);
  230. begin { procedure pow }
  231.    if odd(num2.n[1]) then
  232.       result.s := num1.s
  233.    else
  234.       result.s := 1;
  235.  
  236.    zero(result);
  237.    add_ni(result, 1, result);
  238.    while (numcmp(num2, zero_n) <> 0) do
  239.       begin
  240.       mul(result, num1, result);
  241.       add_ni(num2, -1, num2);
  242.       end;
  243. end; { procedure pow }
  244.  
  245. procedure fix_bit(var num : number);
  246. begin { procedure fix_bit }
  247.    if num.s = -1 then
  248.       begin
  249.       num.b := (neg_one - num.b);
  250.       add_ni(num, 1, num);
  251.       end;
  252.    num.s := 1;
  253. end; { procedure fix_bit }
  254.  
  255. procedure bit_and(num1, num2 : number; var result : number);
  256. begin { procedure bit_and }
  257.    fix_bit(num1);
  258.    fix_bit(num2);
  259.    result.b := num1.b * num2.b
  260. end; { procedure bit_and }
  261.  
  262. procedure bit_or(num1, num2 : number; var result : number);
  263. begin { procedure bit_or }
  264.    fix_bit(num1);
  265.    fix_bit(num2);
  266.    result.b := num1.b + num2.b;
  267.    result.s := 1;
  268. end; { procedure bit_or }
  269.  
  270. procedure bit_xor(num1, num2 : number; var result : number);
  271. begin { procedure bit_xor }
  272.    fix_bit(num1);
  273.    fix_bit(num2);
  274.    result.b := (num1.b - num2.b) + (num2.b - num1.b);
  275.    result.s := 1;
  276. end; { procedure bit_xor }
  277.  
  278.  
  279. function do_eval(num2, num1, op : str; var result : str) : boolean;
  280. var
  281.    dec1, dec2 : number;
  282.    dec_result,
  283.    dummy      : number;
  284.    valid      : boolean;
  285. begin { function do_eval }
  286.    valid := true;
  287.    if (num1 = '') or (num2 = '') then
  288.       begin
  289.       writeln('Unbalanced expression.');
  290.       writeln(' - missing operands.');
  291.       valid := false;
  292.       end
  293.    else if not todec(num1, in_rad, dec1) then
  294.       valid := false
  295.    else if not todec(num2, in_rad, dec2) then
  296.       valid := false
  297.    else if op = '+' then
  298.       add(dec1, dec2, dec_result)
  299.    else if op = '-' then
  300.       sub(dec1, dec2, dec_result)
  301.    else if op = '*' then
  302.       mul(dec1, dec2, dec_result)
  303.    else if op = '/' then
  304.       if numcmp(dec2, zero_n) = 0 then
  305.          begin
  306.          writeln('Division by zero.');
  307.          valid := false;
  308.          end
  309.       else
  310.          dvd(dec1, dec2, dec_result, dummy)
  311.    else if op = '%' then
  312.       if numcmp(dec2, zero_n) = 0 then
  313.          begin
  314.          writeln('Division by zero.');
  315.          valid := false;
  316.          end
  317.       else
  318.          dvd(dec1, dec2, dummy, dec_result)
  319.    else if op = '**' then
  320.       pow(dec1, dec2, dec_result)
  321.    else if op = '&' then
  322.       bit_and(dec1, dec2, dec_result)
  323.    else if op = '|' then
  324.       bit_or(dec1, dec2, dec_result)
  325.    else if op = '^' then
  326.       bit_xor(dec1, dec2, dec_result)
  327.    else
  328.       begin
  329.       writeln('Invalid operator: ''', op, '''.');
  330.       valid := false;
  331.       end;
  332.    if valid then
  333.       toother(dec_result, in_rad, result, false);
  334.    do_eval := valid;
  335. end; { function do_eval }
  336.  
  337. procedure factoral(num : str; var result : str);
  338. var
  339.    result_n,
  340.    num_n     : number;
  341. begin { procedure negate }
  342.  
  343.    zero(result_n);
  344.    add_ni(result_n, 1, result_n);
  345.  
  346.    if not todec(num, in_rad, num_n) then
  347.       begin
  348.       result := '';
  349.       valid  := false;
  350.       end
  351.    else
  352.       begin
  353.       while numcmp(num_n, zero_n) <> 0 do
  354.          begin
  355.          mul(result_n, num_n, result_n);
  356.          add_ni(num_n, -1, num_n);
  357.          end;
  358.       toother(result_n, in_rad, result, false);
  359.       end;
  360. end; { procedure negate }
  361.  
  362. procedure negate(num : str; var result : str);
  363. begin { procedure negate }
  364.    if num[1] = '-' then
  365.       result := copy(num, 2, length(num) - 1)
  366.    else
  367.       result := '-' + num;
  368. end; { procedure negate }
  369.  
  370. begin { function eval_post }
  371.    valid     := true;
  372.    num_stack := nil;
  373.    while get_token(expr, token) and valid do
  374.       if is_num(token) then
  375.          push(num_stack, token)
  376.       else if (token = '!') then
  377.          begin
  378.          factoral(pop(num_stack), result);
  379.          push(num_stack, result);
  380.          end
  381.       else if (token = '~') then
  382.          begin
  383.          negate(pop(num_stack), result);
  384.          push(num_stack, result);
  385.          end
  386.       else if do_eval(pop(num_stack), pop(num_stack), token, result) then
  387.          push(num_stack, result)
  388.       else
  389.          valid := false;
  390.    if valid and empty(num_stack) then
  391.       begin
  392.       writeln(' - too many operator(s).');
  393.       valid := false;
  394.       end
  395.    else if valid then
  396.       valid := todec(pop(num_stack), in_rad, val);
  397.    if not empty(num_stack) then
  398.       begin
  399.       writeln('Unbalanced expression ');
  400.       writeln(' - missing operator(s).');
  401.       valid := false;
  402.       end;
  403.    eval_post := valid;
  404. end; { function eval_post }
  405.  
  406.