home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 13 / 13.iso / p / p065 / 3.img / CALC.LSP < prev    next >
Encoding:
Lisp/Scheme  |  1990-09-07  |  15.8 KB  |  503 lines

  1. ;;;   CALC.lsp
  2. ;;;   Copyright (C) 1990 by Autodesk, Inc.
  3. ;;;  
  4. ;;;   THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. 
  5. ;;;   ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF 
  6. ;;;   MERCHANTABILITY ARE HEREBY DISCLAIMED.
  7. ;;; 
  8. ;;;   by Jan S. Yoder
  9. ;;;   01 February 1990
  10. ;;;
  11. ;;;--------------------------------------------------------------------------;
  12. ;;; DESCRIPTION
  13. ;;;   This is a command line implementation of an TI type calculator.  It 
  14. ;;;   supports addition, subtraction, multiplication, division, square roots,
  15. ;;;   raising Y to the x power, and numerous memory functions.  There is no
  16. ;;;   built-in limit to the number of lisp variables that may be assigned -
  17. ;;;   this is limited by the user's memory.  Values may be stored to variables,
  18. ;;;   listed, deleted, and used in calculations as desired.
  19. ;;;
  20. ;;;   There is also support for sine, cosine, tangent and the Arc functions;
  21. ;;;   Arcsine, Arccosine, and Arctangent.  All angles are in degrees, radians 
  22. ;;;   and gradians are not supported.
  23. ;;;
  24. ;;;   This function tries to be understanding about unit types and precision,
  25. ;;;   but no claim is made that it is universally adequate about performing 
  26. ;;;   said task.   For instance, if the user does several multiplication 
  27. ;;;   sequences, the printed display will show first units, then square units,
  28. ;;;   cubic units, and finally revert back to units, as I don't quite know
  29. ;;;   what to call forth order dimensions - perhaps teracted units.  There is 
  30. ;;;   also no way to tell whether a number is a unit or unitless multiplier.
  31. ;;;--------------------------------------------------------------------------;
  32. ;;;
  33. (defun myerror (s)                    ; If an error (such as CTRL-C) occurs
  34.                                       ; while this command is active...
  35.   (if (/= s "Function cancelled")
  36.     (princ (strcat "\nError: " s))
  37.   )
  38.   (setvar "cmdecho" ocmd)             ; Restore saved modes
  39.   (setvar "blipmode" oblp)
  40.   (setq *error* olderr)               ; Restore old *error* handler
  41.   (princ)
  42. )
  43. ;;;
  44. ;;; Main control function.
  45. ;;;
  46. (defun a:calc (task / calc_n calc_a calc_s temp sbtask save_m)
  47.   (setvar "cmdecho" 0)
  48.   (command "undo" "group")
  49.   (setq calc_n 0)
  50.   (menucmd "s=calc")
  51.   (cond
  52.     ;; The trig functions; sine, cosine, tangent, arctangent
  53.     ((= task "Trig")                  
  54.       (setq calc_c 1)
  55.       (cal_tr)
  56.     )
  57.     ;; The square root of calc_m
  58.     ((= task "Sq-rt")                 
  59.       (setq calc_c 1)
  60.       (cal_sq)
  61.     )
  62.     ;; calc_m to the x power.  Negative numbers used as x
  63.     ;; result in fractions as such - (1/mt)^x
  64.     ((= task "Y")       
  65.       (setq calc_c 1)
  66.       (cal_yx)
  67.     )
  68.     ;; Memory subfunctions
  69.     ((= task "Mem")     
  70.       (setq calc_c 1)
  71.       (cal_mm)
  72.     )
  73.     ;; Add, subtract, multiply and divide
  74.     (T
  75.       (setq calc_n (getdist "Next number: "))
  76.       (if calc_n 
  77.         (cond
  78.           ;; add the number to the display
  79.           ((= task "+") 
  80.            (setq calc_c 1
  81.                   calc_m (+ calc_m calc_n)
  82.                  calc_a (strcat (rtos calc_m) 
  83.                           (if (= (getvar "lunits") 4) (strcat
  84.                             ", or " (rtos calc_m 2)) "") " units. ")
  85.             )
  86.           )
  87.           ;; subtract the number from the display
  88.           ((= task "-") 
  89.             (setq calc_c 1
  90.                   calc_m (- calc_m calc_n)
  91.                   calc_a (strcat (rtos calc_m) 
  92.                           (if (= (getvar "lunits") 4) (strcat
  93.                             ", or " (rtos calc_m 2)) "") " units. ")
  94.             )
  95.           )
  96.           ;; multiply the display by the number
  97.           ((= task "*") 
  98.             ;; Take care of power to a number when multiplied
  99.             (setq calc_c (1+ calc_c)) ; placed count here to 
  100.             (cond                     ; figure out whether to put
  101.               ((= calc_c 2) (setq calc_s " square")); square if 2 times
  102.               ((= calc_c 3) (setq calc_s " cubic")) ; cubic if 3 times
  103.               (T (setq calc_s ""))
  104.             )
  105.             (setq calc_m (* calc_m calc_n))
  106.             (if (= (getvar "lunits") 4)
  107.               (if (or (= calc_c 2) (= calc_c 3))
  108.                 (setq calc_a (strcat "\n" (rtos (/ calc_m 12) 2)
  109.                                      calc_s "Feet or " 
  110.                                      (rtos calc_m 2) calc_s " Inches" ))
  111.                 (setq calc_a (strcat (rtos calc_m) calc_s " units. "))
  112.               )
  113.               (setq calc_a (strcat (rtos calc_m 2) calc_s " units. "))
  114.             )
  115.           )
  116.           ;; divide the display by the number
  117.           ((= task "/") 
  118.             (setq calc_c 1
  119.                   calc_m (/ calc_m calc_n)
  120.                   calc_a (strcat (rtos calc_m) 
  121.                           (if (= (getvar "lunits") 4) (strcat
  122.                             ", or " (rtos calc_m 2)) "") " units. ")
  123.             )
  124.           )
  125.           (T                          ; error
  126.             (exit)
  127.           )
  128.         )
  129.       )
  130.       ;; Display the result
  131.       (if calc_n (princ (strcat "\n" calc_a)))
  132.     )
  133.   )
  134. )
  135. ;;;
  136. ;;; Trig functions
  137. ;;;
  138. (defun cal_tr ()
  139.   (menucmd "s=calc3")
  140.   (if (null sbtask) (setq sbtask "Exit"))
  141.   (initget "ACosine ASine ATangent Sine Cosine Tangent Exit") 
  142.   (setq temp (getkword (strcat 
  143.     "\nTrig: ACosine ASine ATangent Cosine Sine Tangent <" sbtask ">: ")))
  144.   (if temp (setq sbtask temp))
  145.   (cond 
  146.     ((= sbtask "ACosine")
  147.       (cal_ac)
  148.     )
  149.     ((= sbtask "ASine")
  150.       (cal_as)
  151.     )
  152.     ((= sbtask "ATangent")
  153.       (setq save_m calc_m
  154.             calc_m    (* (atan calc_m) (/ 180 pi))
  155.       )
  156.       (cal_pr "The arctangent of " save_m " is " calc_m " degrees. ")
  157.     )
  158.     ((= sbtask "Cosine")
  159.       (setq save_m calc_m
  160.             calc_m    (cos (/ calc_m (/ 180 pi)))
  161.       )
  162.       (cal_pr "The cosine of " save_m " degrees is " calc_m ". ")
  163.     )
  164.     ((= sbtask "Sine")
  165.       (setq save_m calc_m
  166.             calc_m    (sin (/ calc_m (/ 180 pi)))
  167.       )
  168.       (cal_pr "The sine of " save_m " degrees is " calc_m ". ")
  169.     )
  170.     ((= sbtask "Tangent")
  171.       (setq save_m calc_m
  172.             calc_m    (/ (sin (/ calc_m (/ 180 pi))) 
  173.                          (cos (/ calc_m (/ 180 pi))))
  174.       )
  175.       (cal_pr "The tangent of " save_m " degrees is " calc_m ". ")
  176.     )
  177.     (T
  178.       (princ)
  179.     )
  180.   )
  181. )
  182. ;;;
  183. ;;; Arc-Cosine function.
  184. ;;; The function must be bound between the range -1 <= calc_m <= 1
  185. ;;; arc_cos(x) = arc_tan(x/sqrt(1-x^2))
  186. ;;;
  187. (defun cal_ac ()
  188.   (if (and (< calc_m 1.0) 
  189.            (> calc_m -1.0))
  190.     (progn
  191.       (setq save_m calc_m
  192.             calc_m (* (/ 180 pi) 
  193.                       (atan (sqrt (- 1 (expt calc_m 2))) calc_m))
  194.       )
  195.       (cal_pr "The arccosine of " save_m " is " calc_m " degrees. ")
  196.     )
  197.     (cond
  198.       ((= calc_m 1.0)
  199.         (cal_pr "The arccosine of " calc_m " is " (eval 0.0) " degrees. ")
  200.         (setq calc_m 0)
  201.       )
  202.       ((= calc_m -1.0)
  203.         (cal_pr "The arccosine of " calc_m " is " (eval 180.0) " degrees. ")
  204.         (setq calc_m 180)
  205.       )
  206.       (progn
  207.         (cal_pr "The arccosine of " calc_m " is undefined. " nil "")
  208.         (princ "\nValid range is (0 <= Input value < 1).")
  209.       )
  210.     )
  211.   )
  212. )
  213. ;;;
  214. ;;; Arc-Sine function.
  215. ;;; The function must be bound between the range -1 <= calc_m <= 1
  216. ;;; arc_sin(x) = PI/2 - arc_cos(x)
  217. ;;;
  218. (defun cal_as ()
  219.   (if (and (< calc_m 1.0) 
  220.            (> calc_m -1.0))
  221.     (progn
  222.       (setq save_m calc_m
  223.             calc_m (- 90.0 
  224.                       (* (/ 180 pi) 
  225.                          (atan (sqrt (- 1 (expt calc_m 2))) calc_m)))
  226.       )
  227.       (cal_pr "The arcsine of " save_m " is " calc_m " degrees. ")
  228.     )
  229.     (cond
  230.       ((= calc_m 1.0)
  231.         (cal_pr "The arcsine of " calc_m " is " (eval 90.0) " degrees. ")
  232.         (setq calc_m 90)
  233.       )
  234.       ((= calc_m -1.0)
  235.         (cal_pr "The arcsine of " calc_m " is " (eval -90.0) " degrees. ")
  236.         (setq calc_m -90)
  237.       )
  238.       (progn
  239.         (cal_pr "The arcsine of " calc_m " is undefined. " nil "")
  240.         (princ "\nValid range is (0 <= Input value < 1).")
  241.       )
  242.     )
  243.   )
  244. )
  245. ;;;
  246. ;;; Print a concatenated string with a symbols value.
  247. ;;;
  248. (defun cal_pr (str1 val1 str2 val2 str3)
  249.   (princ (strcat "\n" 
  250.                  str1 
  251.                  (if val1 (rtos val1 2) "")
  252.                  str2 
  253.                  (if val2 (rtos val2 2) "")
  254.                  str3 "\n"))
  255. )
  256. ;;;
  257. ;;; Calculate the square of the number.
  258. ;;;
  259. (defun cal_sq ()
  260.   (setq save_m calc_m
  261.         calc_m (sqrt calc_m)
  262.   )
  263.   (if (= (getvar "lunits") 4)
  264.     (progn
  265.       (princ (strcat "\nThe square root of " (rtos save_m) " is " 
  266.                                      (rtos calc_m) ", or"))
  267.       (princ (strcat "\nthe square root of " (rtos save_m 2) " is " 
  268.                                      (rtos calc_m 2) ". "))
  269.     )
  270.     (cal_pr "The square root of " save_m " is " calc_m ". ")
  271.   )
  272. )
  273. ;;;
  274. ;;; Calculate the result of Y to the x power
  275. ;;;
  276. (defun cal_yx ()
  277.   (setq calc_a (getreal "\Enter the power of x: "))
  278.   (if (= calc_a 0.0) 
  279.     (princ "\nInvalid power of x. ")
  280.     (progn
  281.       (setq save_m calc_m
  282.             calc_m    (expt calc_m calc_a))
  283.       (princ (strcat "\n" (rtos save_m 2) 
  284.                      " to the power of " (rtos calc_a 2) 
  285.                      " is " (rtos calc_m 2)
  286.                      (if (< calc_a 0)
  287.                        (strcat " or 1/" (rtos (/ 1.0 calc_m) 2))
  288.                        ""
  289.                      )
  290.                      ". \n"
  291.             )
  292.       )
  293.     )
  294.   )
  295. )
  296. ;;;
  297. ;;; Memory functions -- main function
  298. ;;;
  299. (defun cal_mm ()
  300.   (menucmd "s=calc2")
  301.   (if (null sbtask) (setq sbtask "Set"))
  302.   (initget (strcat "+ - * / Delete Set Recall List Exit"
  303.                    "ADd SUbtract MUltiply DIvide")) 
  304.   (setq temp (getkword (strcat 
  305.     "\nMem : Delete/Exit/List/Recall/Set or + - * / <" sbtask ">: ")))
  306.   (if temp (setq sbtask temp))
  307.   (cond 
  308.     ;; List the non-nil declared variables in the calculator
  309.     ((= sbtask "List") 
  310.       (cal_ml) 
  311.     )
  312.     ((= sbtask "Exit")
  313.       (princ)
  314.     )
  315.     (T
  316.       (cal_mt)
  317.     )
  318.   )
  319. )
  320. ;;;
  321. ;;; Memory list function.
  322. ;;;
  323. (defun cal_ml ()
  324.   (setq nwlist '())
  325.   (if (null vlist)
  326.     (princ "\nNo variables defined. ")
  327.     (progn
  328.       (foreach n vlist 
  329.         (princ (if (or (= (type (eval (read n))) 'REAL)
  330.                        (= (type (eval (read n))) 'INT))
  331.                  (progn
  332.                    (setq nwlist (append nwlist (list n)))
  333.                    (if (= (getvar "lunits") 4)
  334.                      (strcat "\n     " n " = " 
  335.                              (rtos (eval (read n)))
  336.                              ", or " 
  337.                              (rtos (eval (read n)) 2)
  338.                      )              
  339.                      (strcat "\n     " n " = " 
  340.                              (rtos (eval (read n)))
  341.                      )              
  342.                    )              
  343.                  )
  344.                  (princ)
  345.                )
  346.         )
  347.       )
  348.     )
  349.   )
  350.   (if nwlist 
  351.     (progn
  352.       (setq vlist  nwlist 
  353.             nwlist nil
  354.       )
  355.     )
  356.   )
  357. )
  358. ;;;
  359. ;;; Memory operation functions.
  360. ;;;
  361. (defun cal_mt ()
  362.   (setq v_name (getstring (cond 
  363.     ((= sbtask "+") (strcat "Add " (rtos calc_m 2) " to: "))
  364.     ((= sbtask "-") (strcat "Subtract " (rtos calc_m 2) " from: "))
  365.     ((= sbtask "*") (strcat "Multiply by "  (rtos calc_m 2) ": "))
  366.     ((= sbtask "/") (strcat "Divide by " (rtos calc_m 2) ": "))
  367.     ((= sbtask "Delete") "Delete (All = *C): ")
  368.     ((= sbtask "Set") "Set: ")
  369.     ((= sbtask "Recall") "Recall: ")
  370.   )))
  371.   (if (or (= v_name "") 
  372.           (null v_name)
  373.           (and (/= (ascii v_name) 42)
  374.                (< (ascii v_name) 65)
  375.           )
  376.           (and (> (ascii v_name) 90)
  377.                (< (ascii v_name) 97)
  378.           )
  379.           (> (ascii v_name) 122)
  380.       )
  381.     (progn 
  382.       (setq v_name "")
  383.     )
  384.  
  385.     ;; Set up list of variable names and avoid 
  386.     ;; duplicate variable names on the list
  387.  
  388.     (progn 
  389.       (if (= (strcase v_name) "*C")   ; if deleting all variables
  390.          (progn                     
  391.            (princ "\nSetting all variables nil.")
  392.            (setq vlist nil)
  393.          )
  394.          (progn                       ; else
  395.            (setq v_name (strcase v_name)
  396.                  vlist  (if (null vlist)
  397.                           (list v_name)
  398.                           (progn
  399.                             (if (not (member v_name vlist))
  400.                               (append vlist (list v_name))
  401.                               vlist
  402.                             )
  403.                           )
  404.                         )
  405.           )
  406.           (cond
  407.             ;; set the variable name to the number
  408.             ((= sbtask "Set") 
  409.               (set (read v_name) calc_m)
  410.               (eval (read v_name))
  411.             )
  412.             ;; recall the value of the variable
  413.             ((= sbtask "Recall")  
  414.               (setq calc_m (eval (read v_name)))
  415.               (print calc_m)
  416.             )
  417.             ;; delete the variable (set to nil)
  418.             ((= sbtask "Delete")  
  419.               (set (read v_name) nil)
  420.             )
  421.             ;; add the number to the variable
  422.             ((= sbtask "+") 
  423.               (set (read v_name) (+ (eval (read v_name)) calc_m))
  424.               (setq calc_m (read v_name))
  425.               (print (eval (read v_name)))
  426.             )
  427.             ;; subtract the number from the variable
  428.             ((= sbtask "-") 
  429.               (set (read v_name) (- (eval (read v_name)) calc_m))
  430.               (setq calc_m (read v_name))
  431.               (print (eval (read v_name)))
  432.             )
  433.             ;; multiply the value of the variable by the   number
  434.             ((= sbtask "*") 
  435.               (set (read v_name) (* (eval (read v_name)) calc_m))
  436.               (setq calc_m (read v_name))
  437.               (print (eval (read v_name)))
  438.             )
  439.             ;; divide the value of the variable by the n  umber
  440.             ((= sbtask "/") 
  441.               (set (read v_name) (/ (eval (read v_name)) calc_m))
  442.               (setq calc_m (read v_name))
  443.               (print (eval (read v_name)))
  444.             )
  445.             ((null (eval (read v_name)))
  446.                (princ "\nNot a valid lisp symbol. ")
  447.             )
  448.           )
  449.         )
  450.       )
  451.     )
  452.   )
  453. )
  454. ;;;
  455. ;;; C:calc definition
  456. ;;;
  457. (defun c:calc (/ olderr ocmd oblp calver cal_er cal_oe s calc_m 
  458.                  temp task calc_c hlf_pi nwlist)
  459.  
  460.   (setq calver "1.00")
  461.   ;;
  462.   ;; Body of CALC function
  463.   ;;
  464.  
  465.   (setq olderr  *error*
  466.         *error* myerror)
  467.   (setq ocmd (getvar "cmdecho"))
  468.   (setq oblp (getvar "blipmode"))
  469.   (setvar "cmdecho" 0)
  470.   (setq task "Clear" calc_c 1 hlf_pi (/ pi 2))
  471.   (princ (strcat "\nCALC, Version " calver ", (c) 1990 by Autodesk, Inc. "))
  472.   (setq calc_m (getdist "\nFirst number: "))
  473.   (while (and calc_m (/= task "Exit"))
  474.     (menucmd "s=calc")
  475.     (initget (strcat "+ - * / Clear Mem Y Sq-rt Trig Exit "
  476.                      " ADd SUbtract MUltiply DIvide")) 
  477.     (setq temp (getkword (strcat    
  478.       "\nCalc: Clear/Exit/Mem/Sq-rt/Trig/Y^x or + - * / <" task ">: ")))
  479.     (if temp (setq task temp))   
  480.     (if (= task "Clear")
  481.       (setq calc_m (getdist "\nFirst number: "))
  482.       (if (and calc_m (/= task "Exit"))
  483.         (a:calc task)
  484.       )
  485.     )
  486.   )
  487.   ;; Delete all "nil" entries from the variable list when exiting
  488.   (setq nwlist '())
  489.   (foreach n vlist 
  490.     (if (null (eval (read n)))
  491.        (eval (read n))
  492.        (setq nwlist (append nwlist (list n)))
  493.     )
  494.   )
  495.   (if nwlist (setq vlist nwlist nwlist nil))
  496.   (setvar "cmdecho" ocmd)
  497.   (setvar "blipmode" oblp)
  498.   (setq *error* olderr)               ; Restore old *error* handler
  499.   (princ)
  500. )
  501. (princ "\n\tC:CALC.LSP loaded.  Start command with CALC.")
  502. (princ)
  503.