home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume13 / gmcalc / part10 < prev    next >
Encoding:
Text File  |  1990-06-05  |  57.1 KB  |  1,896 lines

  1. Newsgroups: comp.sources.misc
  2. From: daveg@csvax.caltech.edu (David Gillespie)
  3. Subject: v13i036: Emacs Calculator 1.01, part 10/19
  4. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  5.  
  6. Posting-number: Volume 13, Issue 36
  7. Submitted-by: daveg@csvax.caltech.edu (David Gillespie)
  8. Archive-name: gmcalc/part10
  9.  
  10. ---- Cut Here and unpack ----
  11. #!/bin/sh
  12. # this is part 10 of a multipart archive
  13. # do not concatenate these parts, unpack them in order with /bin/sh
  14. # file calc-ext.el continued
  15. #
  16. CurArch=10
  17. if test ! -r s2_seq_.tmp
  18. then echo "Please unpack part 1 first!"
  19.      exit 1; fi
  20. ( read Scheck
  21.   if test "$Scheck" != $CurArch
  22.   then echo "Please unpack part $Scheck next!"
  23.        exit 1;
  24.   else exit 0; fi
  25. ) < s2_seq_.tmp || exit 1
  26. echo "x - Continuing file calc-ext.el"
  27. sed 's/^X//' << 'SHAR_EOF' >> calc-ext.el
  28. X                       ''math-integral-2)
  29. X                 (list 'list
  30. X                       (list 'function
  31. X                         (append '(lambda (u v))
  32. X                             code)))))))
  33. X          (if (symbolp funcs) (list funcs) funcs)))
  34. X)
  35. X(put 'math-defintegral-2 'lisp-indent-hook 1)
  36. X
  37. X(math-defintegral calcFunc-inv
  38. X  (math-integral (math-div 1 u)))
  39. X
  40. X(math-defintegral calcFunc-conj
  41. X  (let ((int (math-integral u)))
  42. X    (and int
  43. X     (list 'calcFunc-conj int))))
  44. X
  45. X(math-defintegral calcFunc-deg
  46. X  (let ((int (math-integral u)))
  47. X    (and int
  48. X     (list 'calcFunc-deg int))))
  49. X
  50. X(math-defintegral calcFunc-rad
  51. X  (let ((int (math-integral u)))
  52. X    (and int
  53. X     (list 'calcFunc-rad int))))
  54. X
  55. X(math-defintegral calcFunc-re
  56. X  (let ((int (math-integral u)))
  57. X    (and int
  58. X     (list 'calcFunc-re int))))
  59. X
  60. X(math-defintegral calcFunc-im
  61. X  (let ((int (math-integral u)))
  62. X    (and int
  63. X     (list 'calcFunc-im int))))
  64. X
  65. X(math-defintegral calcFunc-sqrt
  66. X  (and (equal u math-integ-var)
  67. X       (math-mul '(frac 2 3)
  68. X         (list 'calcFunc-sqrt (math-pow u 3)))))
  69. X
  70. X(math-defintegral calcFunc-exp
  71. X  (and (equal u math-integ-var)
  72. X       (list 'calcFunc-exp u)))
  73. X
  74. X(math-defintegral calcFunc-ln
  75. X  (or (and (equal u math-integ-var)
  76. X       (math-sub (math-mul u (list 'calcFunc-ln u)) u))
  77. X      (and (eq (car u) '*)
  78. X       (math-integral (math-add (list 'calcFunc-ln (nth 1 u))
  79. X                    (list 'calcFunc-ln (nth 2 u)))))
  80. X      (and (eq (car u) '/)
  81. X       (math-integral (math-sub (list 'calcFunc-ln (nth 1 u))
  82. X                    (list 'calcFunc-ln (nth 2 u)))))
  83. X      (and (eq (car u) '^)
  84. X       (math-integral (math-mul (nth 2 u)
  85. X                    (list 'calcFunc-ln (nth 1 u)))))))
  86. X
  87. X(math-defintegral calcFunc-log10
  88. X  (and (equal u math-integ-var)
  89. X       (math-sub (math-mul u (list 'calcFunc-ln u))
  90. X         (math-div u (list 'calcFunc-ln 10)))))
  91. X
  92. X(math-defintegral-2 calcFunc-log
  93. X  (math-integral (math-div (list 'calcFunc-ln u)
  94. X               (list 'calcFunc-ln v))))
  95. X
  96. X(math-defintegral calcFunc-sin
  97. X  (and (equal u math-integ-var)
  98. X       (math-neg (math-from-radians-2 (list 'calcFunc-cos u)))))
  99. X
  100. X(math-defintegral calcFunc-cos
  101. X  (and (equal u math-integ-var)
  102. X       (math-from-radians-2 (list 'calcFunc-sin u))))
  103. X
  104. X(math-defintegral calcFunc-tan
  105. X  (and (equal u math-integ-var)
  106. X       (math-neg (math-from-radians-2
  107. X          (list 'calcFunc-ln (list 'calcFunc-cos u))))))
  108. X
  109. X(math-defintegral calcFunc-arcsin
  110. X  (and (equal u math-integ-var)
  111. X       (math-add (math-mul u (list 'calcFunc-arcsin u))
  112. X         (math-from-radians-2
  113. X          (list 'calcFunc-sqrt (math-sub 1 (math-sqr u)))))))
  114. X
  115. X(math-defintegral calcFunc-arccos
  116. X  (and (equal u math-integ-var)
  117. X       (math-sub (math-mul u (list 'calcFunc-arccos u))
  118. X         (math-from-radians-2
  119. X          (list 'calcFunc-sqrt (math-sub 1 (math-sqr u)))))))
  120. X
  121. X(math-defintegral calcFunc-arctan
  122. X  (and (equal u math-integ-var)
  123. X       (math-sub (math-mul u (list 'calcFunc-arctan u))
  124. X         (math-from-radians-2
  125. X          (math-div (list 'calcFunc-ln (math-add 1 (math-sqr u)))
  126. X                2)))))
  127. X
  128. X(math-defintegral calcFunc-sinh
  129. X  (and (equal u math-integ-var)
  130. X       (list 'calcFunc-cosh u)))
  131. X
  132. X(math-defintegral calcFunc-cosh
  133. X  (and (equal u math-integ-var)
  134. X       (list 'calcFunc-sinh u)))
  135. X
  136. X(math-defintegral calcFunc-tanh
  137. X  (and (equal u math-integ-var)
  138. X       (list 'calcFunc-ln (list 'calcFunc-cosh u))))
  139. X
  140. X(math-defintegral calcFunc-arcsinh
  141. X  (and (equal u math-integ-var)
  142. X       (math-sub (math-mul u (list 'calcFunc-arcsinh u))
  143. X         (list 'calcFunc-sqrt (math-add (math-sqr u) 1)))))
  144. X
  145. X(math-defintegral calcFunc-arccosh
  146. X  (and (equal u math-integ-var)
  147. X       (math-sub (math-mul u (list 'calcFunc-arccosh u))
  148. X         (list 'calcFunc-sqrt (math-sub 1 (math-sqr u))))))
  149. X
  150. X(math-defintegral calcFunc-arctanh
  151. X  (and (equal u math-integ-var)
  152. X       (math-sub (math-mul u (list 'calcFunc-arctan u))
  153. X         (math-div (list 'calcFunc-ln
  154. X                 (math-add 1 (math-sqr u)))
  155. X               2))))
  156. X
  157. X;;; 1 / (ax^2 + bx + c) forms.
  158. X(math-defintegral-2 /
  159. X  (and (not (math-expr-contains u math-integ-var))
  160. X       (let ((p1 (math-is-polynomial v math-integ-var 2))
  161. X         q rq part)
  162. X     (cond ((null p1) nil)
  163. X           ((null (cdr (cdr p1)))
  164. X        (math-mul u (math-div (list 'calcFunc-ln v) (nth 1 p1))))
  165. X           ((math-zerop
  166. X         (setq part (math-add (math-mul 2
  167. X                        (math-mul (nth 2 p1)
  168. X                              math-integ-var))
  169. X                      (nth 1 p1))
  170. X               q (math-sub (math-mul 4
  171. X                         (math-mul (nth 0 p1)
  172. X                               (nth 2 p1)))
  173. X                   (math-sqr (nth 1 p1)))))
  174. X        (math-div (math-mul -2 u) part))
  175. X           ((math-negp q)
  176. X        (setq rq (list 'calcFunc-sqrt (math-neg q)))
  177. X        (math-div (math-mul u
  178. X                    (list 'calcFunc-ln
  179. X                      (math-div (math-add part rq)
  180. X                            (math-sub part rq))))
  181. X              rq))
  182. X           (t
  183. X        (setq rq (list 'calcFunc-sqrt q))
  184. X        (math-div (math-mul 2
  185. X                    (math-mul u
  186. X                          (list 'calcFunc-arctan
  187. X                            (math-div part rq))))
  188. X              rq))))))
  189. X
  190. X
  191. X
  192. X;;; Attempt to reduce lhs = rhs to solve-var = rhs', where solve-var appears
  193. X;;; in lhs but not in rhs or rhs'; return rhs'.
  194. X(defun math-try-solve-for (lhs rhs)    ; uses global values: solve-*.
  195. X  (let (t1 t2 t3)
  196. X    (cond ((equal lhs solve-var)
  197. X       rhs)
  198. X      ((Math-primp lhs)
  199. X       nil)
  200. X      ((setq t2 (math-polynomial-base
  201. X             lhs
  202. X             (function (lambda (b)
  203. X                 (and (setq t1 (math-is-polynomial lhs b 2))
  204. X                      (math-expr-depends b solve-var)
  205. X                      (not (equal b lhs)))))))
  206. X       (if (cdr (cdr t1))
  207. X           (math-try-solve-for
  208. X        t2
  209. X        (if (math-looks-evenp (nth 1 t1))
  210. X            (let ((halfb (math-div (nth 1 t1) 2)))
  211. X              (math-div
  212. X               (math-add
  213. X            (math-neg halfb)
  214. X            (math-solve-get-sign
  215. X             (math-normalize
  216. X              (list 'calcFunc-sqrt
  217. X                (math-add (math-sqr halfb)
  218. X                      (math-mul (math-sub rhs (car t1))
  219. X                            (nth 2 t1)))))))
  220. X               (nth 2 t1)))
  221. X          (math-div
  222. X           (math-add
  223. X            (math-neg (nth 1 t1))
  224. X            (math-solve-get-sign
  225. X             (math-normalize
  226. X              (list 'calcFunc-sqrt
  227. X                (math-add (math-sqr (nth 1 t1))
  228. X                      (math-mul 4
  229. X                        (math-mul (math-sub rhs
  230. X                                    (car t1))
  231. X                              (nth 2 t1))))))))
  232. X           (math-mul 2 (nth 2 t1)))))
  233. X         (and (cdr t1)
  234. X          (math-try-solve-for t2
  235. X                      (math-div (math-sub rhs (car t1))
  236. X                        (nth 1 t1))))))
  237. X      ((eq (car lhs) '+)
  238. X       (cond ((not (math-expr-depends (nth 1 lhs) solve-var))
  239. X          (math-try-solve-for (nth 2 lhs)
  240. X                      (math-sub rhs (nth 1 lhs))))
  241. X         ((not (math-expr-depends (nth 2 lhs) solve-var))
  242. X          (math-try-solve-for (nth 1 lhs)
  243. X                      (math-sub rhs (nth 2 lhs))))))
  244. X      ((memq (car lhs) '(- calcFunc-eq))
  245. X       (cond ((not (math-expr-depends (nth 1 lhs) solve-var))
  246. X          (math-try-solve-for (nth 2 lhs)
  247. X                      (math-sub (nth 1 lhs) rhs)))
  248. X         ((not (math-expr-depends (nth 2 lhs) solve-var))
  249. X          (math-try-solve-for (nth 1 lhs)
  250. X                      (math-add rhs (nth 2 lhs))))))
  251. X      ((eq (car lhs) 'neg)
  252. X       (math-try-solve-for (nth 1 lhs) (math-neg rhs)))
  253. X      ((eq (car lhs) '*)
  254. X       (cond ((not (math-expr-depends (nth 1 lhs) solve-var))
  255. X          (math-try-solve-for (nth 2 lhs)
  256. X                      (math-div rhs (nth 1 lhs))))
  257. X         ((not (math-expr-depends (nth 2 lhs) solve-var))
  258. X          (math-try-solve-for (nth 1 lhs)
  259. X                      (math-div rhs (nth 2 lhs))))))
  260. X      ((eq (car lhs) '/)
  261. X       (cond ((not (math-expr-depends (nth 1 lhs) solve-var))
  262. X          (math-try-solve-for (nth 2 lhs)
  263. X                      (math-div (nth 1 lhs) rhs)))
  264. X         ((not (math-expr-depends (nth 2 lhs) solve-var))
  265. X          (math-try-solve-for (nth 1 lhs)
  266. X                      (math-mul rhs (nth 2 lhs))))
  267. X         ((and (setq t1 (math-is-polynomial (nth 1 lhs) solve-var 2))
  268. X               (setq t2 (math-is-polynomial (nth 2 lhs) solve-var 2)))
  269. X          (math-try-solve-for (math-build-polynomial-expr
  270. X                       (math-poly-mix t2 rhs t1 -1)
  271. X                       solve-var)
  272. X                      0))
  273. X         ((setq t3 (math-polynomial-base
  274. X                (nth 1 lhs)
  275. X                (function (lambda (b)
  276. X                    (and (math-expr-depends b solve-var)
  277. X                         (setq t1 (math-is-polynomial
  278. X                               (nth 1 lhs) b 2))
  279. X                         (setq t2 (math-is-polynomial
  280. X                               (nth 2 lhs) b 2)))))))
  281. X          (math-try-solve-for (math-build-polynomial-expr
  282. X                       (math-poly-mix t2 rhs t1 -1)
  283. X                       t3)
  284. X                      0))))
  285. X      ((eq (car lhs) '^)
  286. X       (cond ((not (math-expr-depends (nth 1 lhs) solve-var))
  287. X          (math-try-solve-for
  288. X           (nth 2 lhs)
  289. X           (math-add (math-normalize
  290. X                  (list 'calcFunc-log rhs (nth 1 lhs)))
  291. X                 (math-div
  292. X                  (math-mul 2
  293. X                    (math-mul '(var pi var-pi)
  294. X                          (math-solve-get-int
  295. X                           '(var i var-i))))
  296. X                  (math-normalize
  297. X                   (list 'calcFunc-ln (nth 1 lhs)))))))
  298. X         ((not (math-expr-depends (nth 2 lhs) solve-var))
  299. X          (cond ((math-equal-int (nth 2 lhs) 2)
  300. X             (math-try-solve-for
  301. X              (nth 1 lhs)
  302. X              (math-solve-get-sign
  303. X               (math-normalize (list 'calcFunc-sqrt rhs)))))
  304. X            (t (math-try-solve-for
  305. X                (nth 1 lhs)
  306. X                (math-mul
  307. X                 (math-normalize
  308. X                  (list 'calcFunc-exp
  309. X                    (if (Math-realp (nth 2 lhs))
  310. X                    (math-div (math-mul
  311. X                           '(var pi var-pi)
  312. X                           (math-solve-get-int
  313. X                            '(var i var-i)))
  314. X                          (math-div (nth 2 lhs) 2))
  315. X                      (math-div (math-mul
  316. X                         2
  317. X                         (math-mul
  318. X                          '(var pi var-pi)
  319. X                          (math-solve-get-int
  320. X                           '(var i var-i))))
  321. X                        (nth 2 lhs)))))
  322. X                 (math-normalize
  323. X                  (list '^
  324. X                    rhs
  325. X                    (math-div 1 (nth 2 lhs)))))))))))
  326. X      ((and (eq (car lhs) '%)
  327. X        (not (math-expr-depends (nth 2 lhs) solve-var)))
  328. X       (math-try-solve-for (nth 1 lhs) (math-add rhs
  329. X                             (math-solve-get-int
  330. X                              (nth 2 lhs)))))
  331. X      ((and (= (length lhs) 2)
  332. X        (symbolp (car lhs))
  333. X        (setq t1 (get (car lhs) 'math-inverse))
  334. X        (setq t2 (funcall t1 rhs)))
  335. X       (math-try-solve-for (nth 1 lhs) (math-normalize t2)))
  336. X      (t
  337. X       (calc-record-why "No inverse known" lhs)
  338. X       nil)))
  339. X)
  340. X
  341. X(defun math-get-from-counter (name)
  342. X  (let ((ctr (assq name calc-command-flags)))
  343. X    (if ctr
  344. X    (setcdr ctr (1+ (cdr ctr)))
  345. X      (setq ctr (cons name 1)
  346. X        calc-command-flags (cons ctr calc-command-flags)))
  347. X    (cdr ctr))
  348. X)
  349. X
  350. X(defun math-solve-get-sign (val)
  351. X  (if solve-full
  352. X      (let ((var (concat "s" (math-get-from-counter 'solve-sign))))
  353. X    (math-mul (list 'var (intern var) (intern (concat "var-" var)))
  354. X          val))
  355. X    (calc-record-why "Choosing positive solution")
  356. X    val)
  357. X)
  358. X
  359. X(defun math-solve-get-int (val)
  360. X  (if solve-full
  361. X      (let ((var (concat "n" (math-get-from-counter 'solve-int))))
  362. X    (math-mul val
  363. X          (list 'var (intern var) (intern (concat "var-" var)))))
  364. X    (calc-record-why "Choosing 0 for arbitrary integer in solution")
  365. X    0)
  366. X)
  367. X
  368. X(defun math-looks-evenp (expr)
  369. X  (if (Math-integerp expr)
  370. X      (math-evenp expr)
  371. X    (if (memq (car expr) '(* /))
  372. X    (math-looks-evenp (nth 1 expr))))
  373. X)
  374. X
  375. X(defun math-solve-for (lhs rhs solve-var solve-full)
  376. X  (if (math-expr-contains rhs solve-var)
  377. X      (math-solve-for (math-sub lhs rhs) 0 solve-var solve-full)
  378. X    (and (math-expr-contains lhs solve-var)
  379. X     (math-try-solve-for lhs rhs)))
  380. X)
  381. X
  382. X(defun calcFunc-solve (expr var)
  383. X  (let ((res (math-solve-for expr 0 var nil)))
  384. X    (if res
  385. X    (list 'calcFunc-eq var res)
  386. X      (list 'calcFunc-solve expr var)))
  387. X)
  388. X
  389. X(defun calcFunc-fsolve (expr var)
  390. X  (let ((res (math-solve-for expr 0 var t)))
  391. X    (if res
  392. X    (list 'calcFunc-eq var res)
  393. X      (list 'calcFunc-fsolve expr var)))
  394. X)
  395. X
  396. X(defun calcFunc-finv (expr var)
  397. X  (let ((res (math-solve-for expr math-integ-var var nil)))
  398. X    (if res
  399. X    (math-normalize (math-expr-subst res math-integ-var var))
  400. X      (list 'calcFunc-finv expr var)))
  401. X)
  402. X
  403. X(defun calcFunc-ffinv (expr var)
  404. X  (let ((res (math-solve-for expr math-integ-var var t)))
  405. X    (if res
  406. X    (math-normalize (math-expr-subst res math-integ-var var))
  407. X      (list 'calcFunc-finv expr var)))
  408. X)
  409. X
  410. X
  411. X(put 'calcFunc-inv 'math-inverse
  412. X     (function (lambda (x) (math-div 1 x))))
  413. X
  414. X(put 'calcFunc-sqrt 'math-inverse
  415. X     (function (lambda (x) (math-sqr x))))
  416. X
  417. X(put 'calcFunc-conj 'math-inverse
  418. X     (function (lambda (x) (list 'calcFunc-conj x))))
  419. X
  420. X(put 'calcFunc-abs 'math-inverse
  421. X     (function (lambda (x) (math-solve-get-sign x))))
  422. X
  423. X(put 'calcFunc-deg 'math-inverse
  424. X     (function (lambda (x) (list 'calcFunc-rad x))))
  425. X
  426. X(put 'calcFunc-rad 'math-inverse
  427. X     (function (lambda (x) (list 'calcFunc-deg x))))
  428. X
  429. X(put 'calcFunc-ln 'math-inverse
  430. X     (function (lambda (x) (list 'calcFunc-exp x))))
  431. X
  432. X(put 'calcFunc-log10 'math-inverse
  433. X     (function (lambda (x) (list 'calcFunc-exp10 x))))
  434. X
  435. X(put 'calcFunc-lnp1 'math-inverse
  436. X     (function (lambda (x) (list 'calcFunc-expm1 x))))
  437. X
  438. X(put 'calcFunc-exp 'math-inverse
  439. X     (function (lambda (x) (math-add (math-normalize (list 'calcFunc-ln x))
  440. X                     (math-mul 2
  441. X                           (math-mul '(var pi var-pi)
  442. X                             (math-solve-get-int
  443. X                              '(var i var-i))))))))
  444. X
  445. X(put 'calcFunc-expm1 'math-inverse
  446. X     (function (lambda (x) (math-add (math-normalize (list 'calcFunc-lnp1 x))
  447. X                     (math-mul 2
  448. X                           (math-mul '(var pi var-pi)
  449. X                             (math-solve-get-int
  450. X                              '(var i var-i))))))))
  451. X
  452. X(put 'calcFunc-sin 'math-inverse
  453. X     (function (lambda (x) (let ((n (math-solve-get-int 1)))
  454. X                 (math-add (math-mul (math-normalize
  455. X                          (list 'calcFunc-arcsin x))
  456. X                         (math-pow -1 n))
  457. X                       (math-mul (math-half-circle t)
  458. X                         n))))))
  459. X
  460. X(put 'calcFunc-cos 'math-inverse
  461. X     (function (lambda (x) (math-add (math-solve-get-sign
  462. X                      (math-normalize
  463. X                       (list 'calcFunc-arccos x)))
  464. X                     (math-solve-get-int
  465. X                      (math-full-circle t))))))
  466. X
  467. X(put 'calcFunc-tan 'math-inverse
  468. X     (function (lambda (x) (math-add (math-normalize (list 'calcFunc-arctan x))
  469. X                     (math-solve-get-int
  470. X                      (math-half-circle t))))))
  471. X
  472. X(put 'calcFunc-arcsin 'math-inverse
  473. X     (function (lambda (x) (math-normalize (list 'calcFunc-sin x)))))
  474. X
  475. X(put 'calcFunc-arccos 'math-inverse
  476. X     (function (lambda (x) (math-normalize (list 'calcFunc-cos x)))))
  477. X
  478. X(put 'calcFunc-arctan 'math-inverse
  479. X     (function (lambda (x) (math-normalize (list 'calcFunc-tan x)))))
  480. X
  481. X(put 'calcFunc-sinh 'math-inverse
  482. X     (function (lambda (x) (let ((n (math-solve-get-int 1)))
  483. X                 (math-add (math-mul (math-normalize
  484. X                          (list 'calcFunc-arctanh x))
  485. X                         (math-pow -1 n))
  486. X                       (math-mul (math-half-circle t)
  487. X                         (math-mul
  488. X                          '(var i var-i)
  489. X                          n)))))))
  490. X
  491. X(put 'calcFunc-cosh 'math-inverse
  492. X     (function (lambda (x) (math-add (math-solve-get-sign
  493. X                      (math-normalize
  494. X                       (list 'calcFunc-arctanh x)))
  495. X                     (math-mul (math-full-circle t)
  496. X                           (math-solve-get-int
  497. X                        '(var i var-i)))))))
  498. X
  499. X(put 'calcFunc-tanh 'math-inverse
  500. X     (function (lambda (x) (math-add (math-normalize
  501. X                      (list 'calcFunc-arctanh x))
  502. X                     (math-mul (math-half-circle t)
  503. X                           (math-solve-get-int
  504. X                        '(var i var-i)))))))
  505. X
  506. X(put 'calcFunc-arcsinh 'math-inverse
  507. X     (function (lambda (x) (math-normalize (list 'calcFunc-sinh x)))))
  508. X
  509. X(put 'calcFunc-arccosh 'math-inverse
  510. X     (function (lambda (x) (math-normalize (list 'calcFunc-cosh x)))))
  511. X
  512. X(put 'calcFunc-arctanh 'math-inverse
  513. X     (function (lambda (x) (math-normalize (list 'calcFunc-tanh x)))))
  514. X
  515. X
  516. X
  517. X(defun calcFunc-taylor (expr var num)
  518. X  (let ((x0 0) (v var))
  519. X    (if (memq (car-safe var) '(+ - calcFunc-eq))
  520. X    (setq x0 (if (eq (car var) '+) (math-neg (nth 2 var)) (nth 2 var))
  521. X          v (nth 1 var)))
  522. X    (or (and (eq (car-safe v) 'var)
  523. X         (math-expr-contains expr v)
  524. X         (natnump num)
  525. X         (let ((accum (math-expr-subst expr v x0))
  526. X           (var2 (if (eq (car var) 'calcFunc-eq)
  527. X                 (cons '- (cdr var))
  528. X               var))
  529. X           (n 0)
  530. X           (nfac 1)
  531. X           (fprime expr))
  532. X           (while (and (<= (setq n (1+ n)) num)
  533. X               (setq fprime (calcFunc-deriv fprime v nil t)))
  534. X         (setq fprime (math-simplify fprime)
  535. X               nfac (math-mul nfac n)
  536. X               accum (math-add accum
  537. X                       (math-div (math-mul (math-pow var2 n)
  538. X                               (math-expr-subst
  539. X                                fprime v x0))
  540. X                         nfac))))
  541. X           (and fprime
  542. X            (math-normalize accum))))
  543. X    (list 'calcFunc-taylor expr var num)))
  544. X)
  545. X
  546. X
  547. X
  548. X
  549. X;;; Simple operations on expressions.
  550. X
  551. X;;; Return number of ocurrences of thing in expr, or nil if none.
  552. X(defun math-expr-contains (expr thing)
  553. X  (cond ((equal expr thing) 1)
  554. X    ((Math-primp expr) nil)
  555. X    (t
  556. X     (let ((num 0))
  557. X       (while (setq expr (cdr expr))
  558. X         (setq num (+ num (or (math-expr-contains (car expr) thing) 0))))
  559. X       (and (> num 0)
  560. X        num))))
  561. X)
  562. X
  563. X;;; Return non-nil if any variable of thing occurs in expr.
  564. X(defun math-expr-depends (expr thing)
  565. X  (if (Math-primp thing)
  566. X      (and (eq (car-safe thing) 'var)
  567. X       (math-expr-contains expr thing))
  568. X    (while (and (setq thing (cdr thing))
  569. X        (not (math-expr-depends expr (car thing)))))
  570. X    thing)
  571. X)
  572. X
  573. X;;; Substitute all occurrences of old for new in expr (non-destructive).
  574. X(defun math-expr-subst (expr old new)
  575. X  (math-expr-subst-rec expr)
  576. X)
  577. X
  578. X(defun math-expr-subst-rec (expr)
  579. X  (cond ((equal expr old) new)
  580. X    ((Math-primp expr) expr)
  581. X    ((memq (car expr) '(calcFunc-deriv
  582. X                calcFunc-tderiv))
  583. X     (if (= (length expr) 2)
  584. X         (if (equal (nth 1 expr) old)
  585. X         (append expr (list new))
  586. X           expr)
  587. X       (list (car expr) (nth 1 expr)
  588. X         (math-expr-subst-rec (nth 2 expr)))))
  589. X    (t
  590. X     (cons (car expr)
  591. X           (mapcar 'math-expr-subst-rec (cdr expr)))))
  592. X)
  593. X
  594. X;;; Various measures of the size of an expression.
  595. X(defun math-expr-weight (expr)
  596. X  (if (Math-primp expr)
  597. X      1
  598. X    (let ((w 1))
  599. X      (while (setq expr (cdr expr))
  600. X    (setq w (+ w (math-expr-weight (car expr)))))
  601. X      w))
  602. X)
  603. X
  604. X(defun math-expr-height (expr)
  605. X  (if (Math-primp expr)
  606. X      0
  607. X    (let ((h 0))
  608. X      (while (setq expr (cdr expr))
  609. X    (setq h (max h (math-expr-height (car expr)))))
  610. X      (1+ h)))
  611. X)
  612. X
  613. X
  614. X
  615. X
  616. X;;; Polynomial operations (to support the integrator and solve-for).
  617. X
  618. X(defun math-collect-terms (expr base)
  619. X  (let ((p (math-is-polynomial expr base 20 t)))
  620. X    (if (cdr p)
  621. X    (math-build-polynomial-expr p base)
  622. X      expr))
  623. X)
  624. X
  625. X;;; If expr is of the form "a + bx + cx^2 + ...", return the list (a b c ...),
  626. X;;; else return nil if not in polynomial form.  If "loose", coefficients
  627. X;;; may contain x, e.g., sin(x) + cos(x) x^2 is a loose polynomial in x.
  628. X(defun math-is-polynomial (expr var &optional degree loose)
  629. X  (let ((poly (math-is-poly-rec expr)))
  630. X    (and (or (null degree)
  631. X         (<= (length poly) (1+ degree)))
  632. X     poly))
  633. X)
  634. X
  635. X(defun math-is-poly-rec (expr)
  636. X  (math-poly-simplify
  637. X   (or (cond ((equal expr var)
  638. X          (list 0 1))
  639. X         ((Math-objectp expr)
  640. X          (list expr))
  641. X         ((memq (car expr) '(+ -))
  642. X          (let ((p1 (math-is-poly-rec (nth 1 expr))))
  643. X        (and p1
  644. X             (let ((p2 (math-is-poly-rec (nth 2 expr))))
  645. X               (and p2
  646. X                (math-poly-mix p1 1 p2
  647. X                       (if (eq (car expr) '+) 1 -1)))))))
  648. X         ((eq (car expr) 'neg)
  649. X          (mapcar 'math-neg (math-is-poly-rec (nth 1 expr))))
  650. X         ((eq (car expr) '*)
  651. X          (let ((p1 (math-is-poly-rec (nth 1 expr))))
  652. X        (and p1
  653. X             (let ((p2 (math-is-poly-rec (nth 2 expr))))
  654. X               (and p2
  655. X                (or (null degree)
  656. X                (<= (- (+ (length p1) (length p2)) 2) degree))
  657. X                (math-poly-mul p1 p2))))))
  658. X         ((eq (car expr) '/)
  659. X          (and (not (math-expr-depends (nth 2 expr) var))
  660. X           (not (Math-zerop (nth 2 expr)))
  661. X           (let ((p1 (math-is-poly-rec (nth 1 expr))))
  662. X             (mapcar (function (lambda (x) (math-div x (nth 2 expr))))
  663. X                 p1))))
  664. X         ((eq (car expr) '^)
  665. X          (and (natnump (nth 2 expr))
  666. X           (let ((p1 (math-is-poly-rec (nth 1 expr)))
  667. X             (n (nth 2 expr))
  668. X             (accum (list 1)))
  669. X             (and p1
  670. X              (or (null degree)
  671. X                  (<= (* (1- (length p1)) n) degree))
  672. X              (progn
  673. X                (while (>= n 1)
  674. X                  (setq accum (math-poly-mul accum p1)
  675. X                    n (1- n)))
  676. X                accum)))))
  677. X         (t nil))
  678. X       (and (or (not (math-expr-depends expr var))
  679. X        loose)
  680. X        (not (memq (car expr) '(vec)))
  681. X        (list expr))))
  682. X)
  683. X
  684. X;;; Check if expr is a polynomial in var; if so, return its degree.
  685. X(defun math-polynomial-p (expr var)
  686. X  (cond ((equal expr var) 1)
  687. X    ((Math-primp expr) 0)
  688. X    ((memq (car expr) '(+ -))
  689. X     (let ((p1 (math-polynomial-p (nth 1 expr) var))
  690. X           (p2 (math-polynomial-p (nth 2 expr) var)))
  691. X       (and p1 p2 (max p1 p2))))
  692. X    ((eq (car expr) '*)
  693. X     (let ((p1 (math-polynomial-p (nth 1 expr) var))
  694. X           (p2 (math-polynomial-p (nth 2 expr) var)))
  695. X       (and p1 p2 (+ p1 p2))))
  696. X    ((eq (car expr) 'neg)
  697. X     (math-polynomial-p (nth 1 expr) var))
  698. X    ((and (eq (car expr) '/)
  699. X          (not (math-expr-depends (nth 1 expr) var)))
  700. X     (math-polynomial-p (nth 1 expr) var))
  701. X    ((and (eq (car expr) '^)
  702. X          (natnump (nth 2 expr)))
  703. X     (let ((p1 (math-polynomial-p (nth 1 expr) var)))
  704. X       (and p1 (* p1 (nth 2 expr)))))
  705. X    ((math-expr-depends expr var) nil)
  706. X    (t 0))
  707. X)
  708. X
  709. X;;; Find the variable (or sub-expression) which is the base of polynomial expr.
  710. X(defun math-polynomial-base (mpb-top-expr &optional mpb-pred)
  711. X  (or mpb-pred
  712. X      (setq mpb-pred (function (lambda (base) (math-polynomial-p
  713. X                           mpb-top-expr base)))))
  714. X  (or (let ((const-ok nil))
  715. X    (math-polynomial-base-rec mpb-top-expr))
  716. X      (let ((const-ok t))
  717. X    (math-polynomial-base-rec mpb-top-expr)))
  718. X)
  719. X
  720. X(defun math-polynomial-base-rec (mpb-expr)
  721. X  (and (not (Math-objvecp mpb-expr))
  722. X       (or (and (memq (car mpb-expr) '(+ - *))
  723. X        (or (math-polynomial-base-rec (nth 1 mpb-expr))
  724. X            (math-polynomial-base-rec (nth 2 mpb-expr))))
  725. X       (and (memq (car mpb-expr) '(/ neg))
  726. X        (math-polynomial-base-rec (nth 1 mpb-expr)))
  727. X       (and (eq (car mpb-expr) '^)
  728. X        (natnump (nth 2 mpb-expr))
  729. X        (math-polynomial-base-rec (nth 1 mpb-expr)))
  730. X       (and (or const-ok (math-expr-contains-vars mpb-expr))
  731. X        (funcall mpb-pred mpb-expr)
  732. X        mpb-expr)))
  733. X)
  734. X
  735. X;;; Return non-nil if expr refers to any variables.
  736. X(defun math-expr-contains-vars (expr)
  737. X  (or (eq (car-safe expr) 'var)
  738. X      (and (not (Math-primp expr))
  739. X       (progn
  740. X         (while (and (setq expr (cdr expr))
  741. X             (not (math-expr-contains-vars (car expr)))))
  742. X         expr)))
  743. X)
  744. X
  745. X;;; Simplify a polynomial in list form by stripping off high-end zeros.
  746. X;;; This always leaves the constant part, i.e., nil->nil and nonnil->nonnil.
  747. X(defun math-poly-simplify (p)
  748. X  (and p
  749. X       (if (Math-zerop (nth (1- (length p)) p))
  750. X       (let ((pp (copy-sequence p)))
  751. X         (while (and (cdr pp)
  752. X             (Math-zerop (nth (1- (length pp)) pp)))
  753. X           (setcdr (nthcdr (- (length pp) 2) pp) nil))
  754. X         pp)
  755. X     p))
  756. X)
  757. X
  758. X;;; Compute ac*a + bc*b for polynomials in list form a, b and
  759. X;;; coefficients ac, bc.  Result may be unsimplified.
  760. X(defun math-poly-mix (a ac b bc)
  761. X  (and (or a b)
  762. X       (cons (math-add (math-mul (or (car a) 0) ac)
  763. X               (math-mul (or (car b) 0) bc))
  764. X         (math-poly-mix (cdr a) ac (cdr b) bc)))
  765. X)
  766. X
  767. X;;; Multiply two polynomials in list form.
  768. X(defun math-poly-mul (a b)
  769. X  (and a b
  770. X       (math-poly-mix b (car a)
  771. X              (math-poly-mul (cdr a) (cons 0 b)) 1))
  772. X)
  773. X
  774. X;;; Build an expression from a polynomial list.
  775. X(defun math-build-polynomial-expr (p var)
  776. X  (if p
  777. X      (let ((accum (car p))
  778. X        (n 0))
  779. X    (while (setq p (cdr p))
  780. X      (setq n (1+ n)
  781. X        accum (math-add (math-mul (car p) (math-pow var n)) accum)))
  782. X    accum))
  783. X)
  784. X
  785. X
  786. X
  787. X
  788. X;;; Units operations.
  789. X
  790. X(defvar math-standard-units
  791. X  '( ;; Length
  792. X     ( m       nil             "*Meter" )
  793. X     ( in      "2.54 cm"             "Inch" )
  794. X     ( ft      "12 in"             "Foot" )
  795. X     ( yd      "3 ft"             "Yard" )
  796. X     ( mi      "5280 ft"         "Mile" )
  797. X     ( au      "1.495979e11 m"       "Astronomical Unit" )
  798. X     ( lyr     "9.46052e15 m"         "Light Year" )
  799. X     ( pc      "3.08568e16 m"         "Parsec" )
  800. X     ( nmi     "1852 m"             "Nautical Mile" )
  801. X     ( fath    "6 ft"             "Fathom" )
  802. X     ( u       "1 um"             "Micron" )
  803. X     ( mil     "in/1000"         "Mil" )
  804. X     ( point   "in/72"             "Point" )
  805. X     ( Ang     "1e-10 m"         "Angstrom" )
  806. X     
  807. X     ;; Area
  808. X     ( hect    "1000 m^2"         "*Hectare" )
  809. X     ( acre    "mi^2 / 640"         "Acre" )
  810. X     ( b       "1e-28 m^2"         "Barn" )
  811. X     
  812. X     ;; Volume
  813. X     ( l       "1e-3 m^3"         "*Liter" )
  814. X     ( L       "1e-3 m^3"         "Liter" )
  815. X     ( gal     "4 qt"             "US Gallon" )
  816. X     ( qt      "2 pt"             "Quart" )
  817. X     ( pt      "2 cup"             "Pint" )
  818. X     ( cup     "8 ozfl"             "Cup" )
  819. X     ( ozfl    "2 tbsp"             "Fluid Ounce" )
  820. X     ( tbsp    "3 tsp"             "Tablespoon" )
  821. X     ( tsp     "4.92892 ml"         "Teaspoon" )
  822. X     ( galC    "4.54609 l"         "Canadian Gallon" )
  823. X     ( galUK   "4.546092 l"         "UK Gallon" )
  824. X     
  825. X     ;; Time
  826. X     ( s       nil             "*Second" )
  827. X     ( min     "60 s"             "Minute" )
  828. X     ( hr      "60 min"             "Hour" )
  829. X     ( day     "24 hr"             "Day" )
  830. X     ( wk      "7 day"             "Week" )
  831. X     ( yr      "365.25 day"         "Year" )
  832. X     ( Hz      "1/s"             "Hertz" )
  833. X
  834. X     ;; Speed
  835. X     ( mph     "mi/hr"             "*Miles per hour" )
  836. X     ( kph     "km/hr"             "Kilometers per hour" )
  837. X     ( knot    "nmi/hr"             "Knot" )
  838. X     ( c       "2.99792458e8 m/s"    "Speed of light" )     
  839. X     
  840. X     ;; Acceleration
  841. X     ( ga      "9.80665 m/s^2"         "*\"g\" acceleration" )
  842. X
  843. X     ;; Mass
  844. X     ( g       nil                   "*Gram" )
  845. X     ( lb      "16 oz"             "Pound (mass)" )
  846. X     ( oz      "28.349523125 g"         "Ounce (mass)" )
  847. X     ( ton     "2000 lb"         "Ton" )
  848. X     ( t       "1000 kg"         "Metric ton" )
  849. X     ( tonUK   "1016.0469088 kg"     "UK ton" )
  850. X     ( lbt     "12 ozt"             "Troy pound" )
  851. X     ( ozt     "31.103475 g"         "Troy ounce" )
  852. X     ( ct      ".2 g"             "Carat" )
  853. X     ( amu     "1.6605655e-24 g"     "Unified atomic mass" )
  854. X
  855. X     ;; Force
  856. X     ( N       "m kg/s^2"         "*Newton" )
  857. X     ( dyn     "1e-5 N"             "Dyne" )
  858. X     ( gf      "9.60665e-3 N"         "Gram (force)" )
  859. X     ( lbf     "4.44822161526 N"     "Pound (force)" )
  860. X     ( kip     "1000 lbf"         "Kilopound (force)" )
  861. X     ( pdl     "0.138255 N"         "Poundal" )
  862. X
  863. X     ;; Energy
  864. X     ( J       "N m"             "*Joule" )
  865. X     ( erg     "1e-7 J"             "Erg" )
  866. X     ( cal     "4.1868 J"         "International Table Calorie" )
  867. X     ( Btu     "1055.05585262 J"     "International Table Btu" )
  868. X     ( eV      "1.6021892e-19 J"     "Electron volt" )
  869. X     ( therm   "105506000 J"         "EEC therm" )
  870. X
  871. X     ;; Power
  872. X     ( W       "J/s"             "*Watt" )
  873. X     ( hp      "745.7 W"         "Horsepower" )
  874. X
  875. X     ;; Temperature
  876. X     ( K       nil                   "*Degree Kelvin"     K )
  877. X     ( dK      "K"             "Degree Kelvin"      K )
  878. X     ( degK    "K"             "Degree Kelvin"      K )
  879. X     ( dC      "K"             "Degree Celsius"      C )
  880. X     ( degC    "K"               "Degree Celsius"      C )
  881. X     ( dF      "(5/9) K"         "Degree Fahrenheit"  F )
  882. X     ( degF    "(5/9) K"         "Degree Fahrenheit"  F )
  883. X
  884. X     ;; Pressure
  885. X     ( Pa      "N/m^2"             "*Pascal" )
  886. X     ( bar     "1e5 Pa"             "Bar" )
  887. X     ( atm     "101325 Pa"         "Standard atmosphere" )
  888. X     ( torr    "atm/760"         "Torr" )
  889. X     ( mHg     "1000 torr"         "Meter of mercury" )
  890. X     ( inHg    "25.4 mmHg"         "Inch of mercury" )
  891. X     ( inH2O   "248.84 Pa"         "Inch of water" )
  892. X     ( psi     "6894.75729317 Pa"    "Pound per square inch" )
  893. X
  894. X     ;; Viscosity
  895. X     ( P       "0.1 Pa s"         "*Poise" )
  896. X     ( St      "1e-4 m^2/s"         "Stokes" )
  897. X
  898. X     ;; Electromagnetism
  899. X     ( A       nil                   "*Ampere" )
  900. X     ( C       "A s"             "Coulomb" )
  901. X     ( Fdy     "96487 C"         "Faraday" )
  902. X     ( e       "1.6021892e-19 C"     "Elementary charge" )
  903. X     ( V       "W/A"             "Volt" )
  904. X     ( ohm     "V/A"             "Ohm" )
  905. X     ( mho     "A/V"             "Mho" )
  906. X     ( S       "A/V"             "Siemens" )
  907. X     ( F       "C/V"             "Farad" )
  908. X     ( H       "Wb/A"             "Henry" )
  909. X     ( T       "Wb/m^2"             "Tesla" )
  910. X     ( G       "1e-4 T"             "Gauss" )
  911. X     ( Wb      "V s"             "Weber" )
  912. X
  913. X     ;; Luminous intensity
  914. X     ( cd      nil                   "*Candela" )
  915. X     ( sb      "1e4 cd/m^2"         "Stilb" )
  916. X     ( lm      "cd sr"             "Lumen" )
  917. X     ( lx      "lm/m^2"             "Lux" )
  918. X     ( ph      "1e4 lx"             "Phot" )
  919. X     ( fc      "10.76 lx"         "Footcandle" )
  920. X     ( lam     "1e4 lm/m^2"         "Lambert" )
  921. X     ( flam    "1.07639104e-3 lam"   "Footlambert" )
  922. X
  923. X     ;; Radioactivity
  924. X     ( Bq      "1/s"               "*Becquerel" )
  925. X     ( Ci      "3.7e8 Bq"         "Curie" )
  926. X     ( Gy      "J/kg"             "Gray" )
  927. X     ( Sv      "Gy"             "Sievert" )
  928. X     ( R       "2.58e-4 C/kg"         "Roentgen" )
  929. X     ( rd      ".01 Sv"             "Rad" )
  930. X     ( rem     "rd"             "Rem" )
  931. X
  932. X     ;; Amount of substance
  933. X     ( mol     nil                   "*Mole" )
  934. X
  935. X     ;; Plane angle
  936. X     ( rad     nil                   "*Radian" )
  937. X     ( circ    "2 pi rad"         "Full circle" )
  938. X     ( deg     "circ/360"            "Degree" )
  939. X     ( arcmin  "deg/60"             "Arc minute" )
  940. X     ( arcsec  "arcmin/60"         "Arc second" )
  941. X     ( grad    "circ/400"            "Grade" )
  942. X
  943. X     ;; Solid angle
  944. X     ( sr      nil             "*Steradian" )
  945. X
  946. X     ;; Other physical quantities (CRC chem & phys, 67th ed)
  947. X     ( h       "6.626176e-34 J s"    "*Planck's constant" )
  948. X     ( hbar    "h / 2 pi"         "Planck's constant" )
  949. X     ( mu0     "4 pi 1e-7 H/m"       "Permeability of vacuum" )
  950. X     ( Grav    "6.6720e-11 N m^2/kg^2"  "Gravitational constant" )
  951. X     ( Nav     "6.0222e23 / mol"     "Avagadro's constant" )
  952. X     ( me      "9.109534e-31 kg"     "Electron rest mass" )
  953. X     ( mp      "1.6726485e-27 kg"    "Proton rest mass" )
  954. X     ( mn      "1.6749543e-27 kg"    "Neutron rest mass" )
  955. X     ( mu      "1.883566e-28 kg"     "Muon rest mass" )
  956. X     ( Ryd     "1.097373177e7 / m"   "Rydberg's constant" )
  957. X     ( k       "Ryd / Nav"         "Boltzmann's constant" )
  958. X     ( fsc     "7.2973506e-3"         "Fine structure constant" )
  959. X     ( mue     "9.284832e-24 J/T"    "Electron magnetic moment" )
  960. X     ( mup     "1.4106171e-26 J/T"   "Proton magnetic moment" )
  961. X     ( R0      "8.31441 J/mol K"     "Molar gas constant" )
  962. X     ( V0      "22.4136 L/mol"         "Standard volume of ideal gas" )
  963. X))
  964. X
  965. X
  966. X(defvar math-additional-units nil
  967. X  "*Additional units table for user-defined units.
  968. XMust be formatted like math-standard-units.
  969. XIf this is changed, be sure to set math-units-table to nil to ensure
  970. Xthat the combined units table will be rebuilt.")
  971. X
  972. X(defvar math-unit-prefixes
  973. X  '( ( ?E  (float 1 18)  "Exa"    )
  974. X     ( ?P  (float 1 15)  "Peta"   )
  975. X     ( ?T  (float 1 12)  "Tera"      )
  976. X     ( ?G  (float 1 9)   "Giga"      )
  977. X     ( ?M  (float 1 6)   "Mega"      )
  978. X     ( ?k  (float 1 3)   "Kilo"      )
  979. X     ( ?K  (float 1 3)   "Kilo"      )
  980. X     ( ?h  (float 1 2)   "Hecto"  )
  981. X     ( ?H  (float 1 2)   "Hecto"  )
  982. X     ( ?D  (float 1 1)   "Deka"      )
  983. X     ( ?d  (float 1 -1)  "Deci"      )
  984. X     ( ?c  (float 1 -2)  "Centi"  )
  985. X     ( ?m  (float 1 -3)  "Milli"  )
  986. X     ( ?u  (float 1 -6)  "Micro"  )
  987. X     ( ?n  (float 1 -9)  "Nano"      )
  988. X     ( ?p  (float 1 -12) "Pico"      )
  989. X     ( ?f  (float 1 -15) "Femto"  )
  990. X     ( ?a  (float 1 -18) "Atto"   )
  991. X))
  992. X
  993. X(defvar math-standard-units-systems
  994. X  '( ( base  nil )
  995. X     ( si    ( ( g   '(* (var kg var-kg) (float 1 -3)) ) ) )
  996. X     ( mks   ( ( g   '(* (var kg var-kg) (float 1 -3)) ) ) )
  997. X     ( cgs   ( ( m   '(* (var cm var-cm) 100         ) ) ) )
  998. X))
  999. X
  1000. X(defvar math-units-table nil
  1001. X  "Internal units table derived from math-defined-units.
  1002. XEntries are (SYMBOL EXPR DOC-STRING TEMP-TYPE BASE-UNITS).")
  1003. X
  1004. X(defvar math-units-table-buffer-valid nil)
  1005. X
  1006. X
  1007. X(defun math-build-units-table ()
  1008. X  (or math-units-table
  1009. X      (let* ((combined-units (append math-additional-units
  1010. X                     math-standard-units))
  1011. X         (unit-list (mapcar 'car combined-units))
  1012. X         (calc-language nil)
  1013. X         (math-expr-opers math-standard-opers)
  1014. X         tab)
  1015. X    (message "Building units table...")
  1016. X    (setq math-units-table-buffer-valid nil)
  1017. X    (setq tab (mapcar (function
  1018. X               (lambda (x)
  1019. X                 (list (car x)
  1020. X                   (and (nth 1 x)
  1021. X                    (if (stringp (nth 1 x))
  1022. X                        (let ((exp (math-read-expr
  1023. X                            (nth 1 x))))
  1024. X                          (if (eq (car-safe exp) 'error)
  1025. X                          (error "Format error in definition of %s in units table: %s"
  1026. X                             (car x) (nth 2 exp))
  1027. X                        exp))
  1028. X                      (nth 1 x)))
  1029. X                   (nth 2 x)
  1030. X                   (nth 3 x)
  1031. X                   (and (not (nth 1 x))
  1032. X                    (list (cons (car x) 1))))))
  1033. X              combined-units))
  1034. X    (let ((math-units-table tab))
  1035. X      (mapcar 'math-find-base-units tab))
  1036. X    (message "Building units table...done")
  1037. X    (setq math-units-table tab)))
  1038. X)
  1039. X
  1040. X(defun math-find-base-units (entry)
  1041. X  (if (eq (nth 4 entry) 'boom)
  1042. X      (error "Circular definition involving unit %s" (car entry)))
  1043. X  (or (nth 4 entry)
  1044. X      (let (base)
  1045. X    (setcar (nthcdr 4 entry) 'boom)
  1046. X    (math-find-base-units-rec (nth 1 entry) 1)
  1047. X    '(or base
  1048. X        (error "Dimensionless definition for unit %s" (car entry)))
  1049. X    (while (eq (cdr (car base)) 0)
  1050. X      (setq base (cdr base)))
  1051. X    (let ((b base))
  1052. X      (while (cdr b)
  1053. X        (if (eq (cdr (car (cdr b))) 0)
  1054. X        (setcdr b (cdr (cdr b)))
  1055. X          (setq b (cdr b)))))
  1056. X    (setq base (sort base 'math-compare-unit-names))
  1057. X    (setcar (nthcdr 4 entry) base)
  1058. X    base))
  1059. X)
  1060. X
  1061. X(defun math-compare-unit-names (a b)
  1062. X  (memq (car b) (cdr (memq (car a) unit-list)))
  1063. X)
  1064. X
  1065. X(defun math-find-base-units-rec (expr pow)
  1066. X  (let ((u (math-check-unit-name expr)))
  1067. X    (cond (u
  1068. X       (let ((ulist (math-find-base-units u)))
  1069. X         (while ulist
  1070. X           (let ((p (* (cdr (car ulist)) pow))
  1071. X             (old (assq (car (car ulist)) base)))
  1072. X         (if old
  1073. X             (setcdr old (+ (cdr old) p))
  1074. X           (setq base (cons (cons (car (car ulist)) p) base))))
  1075. X           (setq ulist (cdr ulist)))))
  1076. X      ((math-scalarp expr))
  1077. X      ((and (eq (car expr) '^)
  1078. X        (integerp (nth 2 expr)))
  1079. X       (math-find-base-units-rec (nth 1 expr) (* pow (nth 2 expr))))
  1080. X      ((eq (car expr) '*)
  1081. X       (math-find-base-units-rec (nth 1 expr) pow)
  1082. X       (math-find-base-units-rec (nth 2 expr) pow))
  1083. X      ((eq (car expr) '/)
  1084. X       (math-find-base-units-rec (nth 1 expr) pow)
  1085. X       (math-find-base-units-rec (nth 2 expr) (- pow)))
  1086. X      ((eq (car expr) 'neg)
  1087. X       (math-find-base-units-rec (nth 1 expr) pow))
  1088. X      ((eq (car expr) 'var)
  1089. X       (or (eq (nth 1 expr) 'pi)
  1090. X           (error "Unknown name %s in defining expression for unit %s"
  1091. X              (nth 1 expr) (car entry))))
  1092. X      (t (error "Malformed defining expression for unit %s" (car entry)))))
  1093. X)
  1094. X
  1095. X
  1096. X(defun math-units-in-expr-p (expr sub-exprs)
  1097. X  (and (consp expr)
  1098. X       (if (eq (car expr) 'var)
  1099. X       (math-check-unit-name expr)
  1100. X     (and (or sub-exprs
  1101. X          (memq (car expr) '(* / ^)))
  1102. X          (or (math-units-in-expr-p (nth 1 expr) sub-exprs)
  1103. X          (math-units-in-expr-p (nth 2 expr) sub-exprs)))))
  1104. X)
  1105. X
  1106. X(defun math-only-units-in-expr-p (expr)
  1107. X  (and (consp expr)
  1108. X       (if (eq (car expr) 'var)
  1109. X       (math-check-unit-name expr)
  1110. X     (if (memq (car expr) '(* /))
  1111. X         (and (math-only-units-in-expr-p (nth 1 expr))
  1112. X          (math-only-units-in-expr-p (nth 2 expr)))
  1113. X       (and (eq (car expr) '^)
  1114. X        (and (math-only-units-in-expr-p (nth 1 expr))
  1115. X             (math-realp (nth 2 expr)))))))
  1116. X)
  1117. X
  1118. X(defun math-single-units-in-expr-p (expr)
  1119. X  (cond ((math-scalarp expr) nil)
  1120. X    ((eq (car expr) 'var)
  1121. X     (math-check-unit-name expr))
  1122. X    ((eq (car expr) '*)
  1123. X     (let ((u1 (math-single-units-in-expr-p (nth 1 expr)))
  1124. X           (u2 (math-single-units-in-expr-p (nth 2 expr))))
  1125. X       (or (and u1 u2 'wrong)
  1126. X           u1
  1127. X           u2)))
  1128. X    ((eq (car expr) '/)
  1129. X     (if (math-units-in-expr-p (nth 2 expr))
  1130. X         'wrong
  1131. X       (math-single-units-in-expr-p (nth 1 expr))))
  1132. X    (t 'wrong))
  1133. X)
  1134. X
  1135. X(defun math-check-unit-name (v)
  1136. X  (and (eq (car-safe v) 'var)
  1137. X       (or (assq (nth 1 v) (or math-units-table (math-build-units-table)))
  1138. X       (let ((name (symbol-name (nth 1 v))))
  1139. X         (and (> (length name) 1)
  1140. X          (assq (aref name 0) math-unit-prefixes)
  1141. X          (or (assq (intern (substring name 1)) math-units-table)
  1142. X              (and (eq (aref name 0) ?M)
  1143. X               (> (length name) 3)
  1144. X               (eq (aref name 1) ?e)
  1145. X               (eq (aref name 2) ?g)
  1146. X               (assq (intern (substring name 3))
  1147. X                 math-units-table)))))))
  1148. X)
  1149. X
  1150. X
  1151. X(defun math-to-standard-units (expr which-standard)
  1152. X  (math-to-standard-rec expr)
  1153. X)
  1154. X
  1155. X(defun math-to-standard-rec (expr)
  1156. X  (if (eq (car-safe expr) 'var)
  1157. X      (let ((u (math-check-unit-name expr))
  1158. X        (base (nth 1 expr)))
  1159. X    (if u
  1160. X        (progn
  1161. X          (if (nth 1 u)
  1162. X          (setq expr (math-to-standard-rec (nth 1 u)))
  1163. X        (let ((st (assq (car u) which-standard)))
  1164. X          (if st
  1165. X              (setq expr (nth 1 st))
  1166. X            (setq expr (list 'var (car u)
  1167. X                     (intern (concat "var-"
  1168. X                             (symbol-name
  1169. X                              (car u)))))))))
  1170. X          (or (null u)
  1171. X          (eq base (car u))
  1172. X          (setq expr (list '*
  1173. X                   (nth 1 (assq (aref (symbol-name base) 0)
  1174. X                        math-unit-prefixes))
  1175. X                   expr)))
  1176. X          expr)
  1177. X      (if (eq base 'pi)
  1178. X          (math-pi)
  1179. X        expr)))
  1180. X    (if (Math-primp expr)
  1181. X    expr
  1182. X      (cons (car expr)
  1183. X        (mapcar 'math-to-standard-rec (cdr expr)))))
  1184. X)
  1185. X
  1186. X(defun math-convert-units (expr new-units)
  1187. X  (if (math-units-in-expr-p expr t)
  1188. X      (math-convert-units-rec expr)
  1189. X    (list '*
  1190. X      (math-to-standard-units (list '/ expr new-units) nil)
  1191. X      new-units))
  1192. X)
  1193. X
  1194. X(defun math-convert-units-rec (expr)
  1195. X  (if (math-units-in-expr-p expr nil)
  1196. X      (list '*
  1197. X        (math-to-standard-units (list '/ expr new-units) nil)
  1198. X        new-units)
  1199. X    (if (Math-primp expr)
  1200. X    expr
  1201. X      (cons (car expr)
  1202. X        (mapcar 'math-convert-units-rec (cdr expr)))))
  1203. X)
  1204. X
  1205. X(defun math-convert-temperature (expr old new)
  1206. X  (let* ((units (math-single-units-in-expr-p expr))
  1207. X     (uold (if old
  1208. X           (if (or (null units)
  1209. X               (equal (nth 1 old) (car units)))
  1210. X               (math-check-unit-name old)
  1211. X             (error "Inconsistent temperature units"))
  1212. X         units))
  1213. X     (unew (math-check-unit-name new)))
  1214. X    (or (and (consp unew) (nth 3 unew))
  1215. X    (error "Not a valid temperature unit"))
  1216. X    (or (and (consp uold) (nth 3 uold))
  1217. X    (error "Not a pure temperature expression"))
  1218. X    (let ((v (car uold)))
  1219. X      (setq expr (list '/ expr (list 'var v
  1220. X                     (intern (concat "var-"
  1221. X                             (symbol-name v)))))))
  1222. X    (or (eq (nth 3 uold) (nth 3 unew))
  1223. X    (cond ((eq (nth 3 uold) 'K)
  1224. X           (setq expr (list '- expr '(float 27315 -2)))
  1225. X           (if (eq (nth 3 unew) 'F)
  1226. X           (setq expr (list '+ (list '* expr '(frac 9 5)) 32))))
  1227. X          ((eq (nth 3 uold) 'C)
  1228. X           (if (eq (nth 3 unew) 'F)
  1229. X           (setq expr (list '+ (list '* expr '(frac 9 5)) 32))
  1230. X         (setq expr (list '+ expr '(float 27315 -2)))))
  1231. X          (t
  1232. X           (setq expr (list '* (list '- expr 32) '(frac 5 9)))
  1233. X           (if (eq (nth 3 unew) 'K)
  1234. X           (setq expr (list '+ expr '(float 27315 -2)))))))
  1235. X    (list '* expr new))
  1236. X)
  1237. X
  1238. X
  1239. X(setq math-simplifying-units nil)
  1240. X
  1241. X(defun math-simplify-units (a)
  1242. X  (let ((math-simplifying-units t))
  1243. X    (math-simplify a))
  1244. X)
  1245. X
  1246. X(math-defsimplify (+ -)
  1247. X  (and math-simplifying-units
  1248. X       (math-units-in-expr-p (nth 1 expr) nil)
  1249. X       (let* ((units (math-extract-units (nth 1 expr)))
  1250. X          (ratio (math-simplify (math-to-standard-units
  1251. X                     (list '/ (nth 2 expr) units) nil))))
  1252. X     (if (math-units-in-expr-p ratio nil)
  1253. X         (progn
  1254. X           (calc-record-why "Inconsistent units" expr)
  1255. X           expr)
  1256. X       (list '* (math-add (math-remove-units (nth 1 expr)) ratio)
  1257. X         units))))
  1258. X)
  1259. X
  1260. X(math-defsimplify /
  1261. X  (and math-simplifying-units
  1262. X       (let ((np (cdr expr))
  1263. X         n nn)
  1264. X     (while (eq (car-safe (setq n (car np))) '*)
  1265. X       (math-simplify-units-divisor (cdr n) (cdr (cdr expr)))
  1266. X       (setq np (cdr (cdr n))))
  1267. X     (math-simplify-units-divisor np (cdr (cdr expr)))
  1268. X     expr))
  1269. X)
  1270. X
  1271. X(defun math-simplify-units-divisor (np dp)
  1272. X  (let ((n (car np))
  1273. X    d dd temp)
  1274. X    (while (eq (car-safe (setq d (car dp))) '*)
  1275. X      (if (setq temp (math-simplify-units-quotient n (nth 1 d)))
  1276. X      (progn
  1277. X        (setcar np (setq n temp))
  1278. X        (setcar (cdr d) 1)))
  1279. X      (setq dp (cdr (cdr d))))
  1280. X    (if (setq temp (math-simplify-units-quotient n d))
  1281. X    (progn
  1282. X      (setcar np (setq n temp))
  1283. X      (setcar dp 1))))
  1284. X)
  1285. X
  1286. X;; Simplify, e.g., "in / cm" to "2.54" in a units expression.
  1287. X(defun math-simplify-units-quotient (n d)
  1288. X  (let ((un (math-check-unit-name n))
  1289. X    (ud (math-check-unit-name d)))
  1290. X    (and un ud
  1291. X     (equal (nth 4 un) (nth 4 ud))
  1292. X     (math-to-standard-units (list '/ n d) nil)))
  1293. X)
  1294. X
  1295. X(math-defsimplify ^
  1296. X  (and math-simplifying-units
  1297. X       (math-realp (nth 2 expr))
  1298. X       (math-simplify-units-pow (nth 1 expr) (nth 2 expr)))
  1299. X)
  1300. X
  1301. X(math-defsimplify calcFunc-sqrt
  1302. X  (and math-simplifying-units
  1303. X       (if (memq (car-safe (nth 1 expr)) '(* /))
  1304. X       (list (car (nth 1 expr))
  1305. X         (list 'calcFunc-sqrt (nth 1 (nth 1 expr)))
  1306. X         (list 'calcFunc-sqrt (nth 2 (nth 1 expr))))
  1307. X     (math-simplify-units-pow (nth 1 expr) '(frac 1 2))))
  1308. X)
  1309. X
  1310. X(math-defsimplify (calcFunc-floor
  1311. X           calcFunc-ceil
  1312. X           calcFunc-round
  1313. X           calcFunc-trunc
  1314. X           calcFunc-float
  1315. X           calcFunc-frac
  1316. X           calcFunc-abs
  1317. X           calcFunc-clean)
  1318. X  (and math-simplifying-units
  1319. X       (if (math-only-units-in-expr-p (nth 1 expr))
  1320. X       (nth 1 expr)
  1321. X     (if (and (memq (car-safe (nth 1 expr)) '(* /))
  1322. X          (or (math-only-units-in-expr-p
  1323. X               (nth 1 (nth 1 expr)))
  1324. X              (math-only-units-in-expr-p
  1325. X               (nth 2 (nth 1 expr)))))
  1326. X         (list (car (nth 1 expr))
  1327. X           (cons (car expr)
  1328. X             (cons (nth 1 (nth 1 expr))
  1329. X                   (cdr (cdr expr))))
  1330. X           (cons (car expr)
  1331. X             (cons (nth 2 (nth 1 expr))
  1332. X                   (cdr (cdr expr)))))))))
  1333. X
  1334. X(defun math-simplify-units-pow (a pow)
  1335. X  (if (and (eq (car-safe a) '^)
  1336. X       (math-check-unit-name (nth 1 a))
  1337. X       (math-realp (nth 2 a)))
  1338. X      (list '^ (nth 1 a) (math-mul pow (nth 2 a)))
  1339. X    (let* ((u (math-check-unit-name a))
  1340. X       (pf (math-to-simple-fraction pow))
  1341. X       (d (and (eq (car-safe pf) 'frac) (nth 2 pf))))
  1342. X      (and u
  1343. X       (eq (car-safe pow) 'frac)
  1344. X       (math-units-are-multiple u d)
  1345. X       (list '^ (math-to-standard-units a nil) pow))))
  1346. X)
  1347. X
  1348. X(defun math-to-simple-fraction (f)
  1349. X  (or (and (eq (car-safe f) 'float)
  1350. X       (or (and (>= (nth 2 f) 0)
  1351. X            (math-scale-int (nth 1 f) (nth 2 f)))
  1352. X           (and (integerp (nth 1 f))
  1353. X            (> (nth 1 f) -1000)
  1354. X            (< (nth 1 f) 1000)
  1355. X            (math-make-frac (nth 1 f)
  1356. X                    (math-scale-int 1 (- (nth 2 f)))))))
  1357. X      f)
  1358. X)
  1359. X
  1360. X(defun math-units-are-multiple (u n)
  1361. X  (setq u (nth 4 u))
  1362. X  (while (and u (= (% (cdr (car u)) n) 0))
  1363. X    (setq u (cdr u)))
  1364. X  (null u)
  1365. X)
  1366. X
  1367. X(math-defsimplify calcFunc-sin
  1368. X  (and math-simplifying-units
  1369. X       (math-units-in-expr-p (nth 1 expr) nil)
  1370. X       (let ((rad (math-simplify-units
  1371. X           (math-evaluate-expr
  1372. X            (math-to-standard-units (nth 1 expr) nil))))
  1373. X         (calc-angle-mode 'rad))
  1374. X     (and (eq (car-safe rad) '*)
  1375. X          (Math-realp (nth 1 rad))
  1376. X          (eq (car-safe (nth 2 rad)) 'var)
  1377. X          (eq (nth 1 (nth 2 rad)) 'rad)
  1378. X          (list 'calcFunc-sin (nth 1 rad)))))
  1379. X)
  1380. X
  1381. X(math-defsimplify calcFunc-cos
  1382. X  (and math-simplifying-units
  1383. X       (math-units-in-expr-p (nth 1 expr) nil)
  1384. X       (let ((rad (math-simplify-units
  1385. X           (math-evaluate-expr
  1386. X            (math-to-standard-units (nth 1 expr) nil))))
  1387. X         (calc-angle-mode 'rad))
  1388. X     (and (eq (car-safe rad) '*)
  1389. X          (Math-realp (nth 1 rad))
  1390. X          (eq (car-safe (nth 2 rad)) 'var)
  1391. X          (eq (nth 1 (nth 2 rad)) 'rad)
  1392. X          (list 'calcFunc-cos (nth 1 rad)))))
  1393. X)
  1394. X
  1395. X(math-defsimplify calcFunc-tan
  1396. X  (and math-simplifying-units
  1397. X       (math-units-in-expr-p (nth 1 expr) nil)
  1398. X       (let ((rad (math-simplify-units
  1399. X           (math-evaluate-expr
  1400. X            (math-to-standard-units (nth 1 expr) nil))))
  1401. X         (calc-angle-mode 'rad))
  1402. X     (and (eq (car-safe rad) '*)
  1403. X          (Math-realp (nth 1 rad))
  1404. X          (eq (car-safe (nth 2 rad)) 'var)
  1405. X          (eq (nth 1 (nth 2 rad)) 'rad)
  1406. X          (list 'calcFunc-tan (nth 1 rad)))))
  1407. X)
  1408. X
  1409. X
  1410. X(defun math-remove-units (expr)
  1411. X  (if (math-check-unit-name expr)
  1412. X      1
  1413. X    (if (Math-primp expr)
  1414. X    expr
  1415. X      (cons (car expr)
  1416. X        (mapcar 'math-remove-units (cdr expr)))))
  1417. X)
  1418. X
  1419. X(defun math-extract-units (expr)
  1420. X  (if (memq (car-safe expr) '(* /))
  1421. X      (cons (car expr)
  1422. X        (mapcar 'math-extract-units (cdr expr)))
  1423. X    (if (math-check-unit-name expr) expr 1))
  1424. X)
  1425. X
  1426. X(defun math-build-units-table-buffer (enter-buffer)
  1427. X  (if (not (and math-units-table math-units-table-buffer-valid
  1428. X        (get-buffer "*Units Table*")))
  1429. X      (let ((buf (get-buffer-create "*Units Table*"))
  1430. X        (uptr (math-build-units-table))
  1431. X        (calc-language (if (eq calc-language 'big) nil calc-language))
  1432. X        (calc-float-format '(float 0))
  1433. X        (calc-group-digits nil)
  1434. X        (calc-number-radix 10)
  1435. X        (calc-point-char ".")
  1436. X        (std nil)
  1437. X        u name shadowed)
  1438. X    (save-excursion
  1439. X      (message "Formatting units table...")
  1440. X      (set-buffer buf)
  1441. X      (setq buffer-read-only nil)
  1442. X      (erase-buffer)
  1443. X      (insert "Calculator Units Table:\n\n")
  1444. X      (insert "Unit    Type  Definition                  Description\n\n")
  1445. X      (while uptr
  1446. X        (setq u (car uptr)
  1447. X          name (nth 2 u))
  1448. X        (if (eq (car u) 'm)
  1449. X        (setq std t))
  1450. X        (setq shadowed (and std (assq (car u) math-additional-units)))
  1451. X        (if (and name
  1452. X             (> (length name) 1)
  1453. X             (eq (aref name 0) ?\*))
  1454. X        (progn
  1455. X          (or (eq uptr math-units-table)
  1456. X              (insert "\n"))
  1457. X          (setq name (substring name 1))))
  1458. X        (insert " ")
  1459. X        (and shadowed (insert "("))
  1460. X        (insert (symbol-name (car u)))
  1461. X        (and shadowed (insert ")"))
  1462. X        (if (nth 3 u)
  1463. X        (progn
  1464. X          (indent-to 10)
  1465. X          (insert (symbol-name (nth 3 u))))
  1466. X          (or std
  1467. X          (progn
  1468. X            (indent-to 10)
  1469. X            (insert "U"))))
  1470. X        (indent-to 14)
  1471. X        (and shadowed (insert "("))
  1472. X        (if (nth 1 u)
  1473. X        (insert (math-format-value (nth 1 u) 80))
  1474. X          (insert (symbol-name (car u))))
  1475. X        (and shadowed (insert ")"))
  1476. X        (indent-to 42)
  1477. X        (if name
  1478. X        (insert name))
  1479. X        (if shadowed
  1480. X        (insert " (redefined above)")
  1481. X          (or (nth 1 u)
  1482. X          (insert " (base unit)")))
  1483. X        (insert "\n")
  1484. X        (setq uptr (cdr uptr)))
  1485. X      (insert "\n\nUnit Prefix Table:\n\n")
  1486. X      (setq uptr math-unit-prefixes)
  1487. X      (while uptr
  1488. X        (setq u (car uptr))
  1489. X        (insert " " (char-to-string (car u)))
  1490. X        (if (equal (nth 1 u) (nth 1 (nth 1 uptr)))
  1491. X        (insert " " (char-to-string (car (car (setq uptr (cdr uptr)))))
  1492. X            "   ")
  1493. X          (insert "     "))
  1494. X        (insert "10^" (int-to-string (nth 2 (nth 1 u))))
  1495. X        (indent-to 15)
  1496. X        (insert "   " (nth 2 u) "\n")
  1497. X        (setq uptr (cdr uptr)))
  1498. X      (insert "\n")
  1499. X      (setq buffer-read-only t)
  1500. X      (message "Formatting units table...done"))
  1501. X    (setq math-units-table-buffer-valid t)
  1502. X    (let ((oldbuf (current-buffer)))
  1503. X      (set-buffer buf)
  1504. X      (goto-char (point-min))
  1505. X      (set-buffer oldbuf))
  1506. X    (if enter-buffer
  1507. X        (pop-to-buffer buf)
  1508. X      (display-buffer buf)))
  1509. X    (if enter-buffer
  1510. X    (pop-to-buffer (get-buffer "*Units Table*"))
  1511. X      (display-buffer (get-buffer "*Units Table*"))))
  1512. X)
  1513. X
  1514. X
  1515. X
  1516. X
  1517. X;;;; User-programmability.
  1518. X
  1519. X;;; Compiling Lisp-like forms to use the math library.
  1520. X
  1521. X(defun math-do-defmath (func args body)
  1522. X  (let* ((fname (intern (concat "calcFunc-" (symbol-name func))))
  1523. X     (doc (if (stringp (car body)) (list (car body))))
  1524. X     (clargs (mapcar 'math-clean-arg args))
  1525. X     (body (math-define-function-body
  1526. X        (if (stringp (car body)) (cdr body) body)
  1527. X        clargs)))
  1528. X    (list 'progn
  1529. X      (if (and (consp (car body))
  1530. X           (eq (car (car body)) 'interactive))
  1531. X          (let ((inter (car body)))
  1532. X        (setq body (cdr body))
  1533. X        (if (or (> (length inter) 2)
  1534. X            (integerp (nth 1 inter)))
  1535. X            (let ((hasprefix nil) (hasmulti nil))
  1536. X              (if (stringp (nth 1 inter))
  1537. X              (progn
  1538. X                (cond ((equal (nth 1 inter) "p")
  1539. X                   (setq hasprefix t))
  1540. X                  ((equal (nth 1 inter) "m")
  1541. X                   (setq hasmulti t))
  1542. X                  (t (error
  1543. X                      "Can't handle interactive code string \"%s\""
  1544. X                      (nth 1 inter))))
  1545. X                (setq inter (cdr inter))))
  1546. X              (if (not (integerp (nth 1 inter)))
  1547. X              (error
  1548. X               "Expected an integer in interactive specification"))
  1549. X              (append (list 'defun
  1550. X                    (intern (concat "calc-"
  1551. X                            (symbol-name func)))
  1552. X                    (if (or hasprefix hasmulti)
  1553. X                    '(&optional n)
  1554. X                      ()))
  1555. X                  doc
  1556. X                  (if (or hasprefix hasmulti)
  1557. X                  '((interactive "P"))
  1558. X                '((interactive)))
  1559. X                  (list
  1560. X                   (append
  1561. X                '(calc-slow-wrapper)
  1562. X                (and hasmulti
  1563. X                     (list
  1564. X                      (list 'setq
  1565. X                        'n
  1566. X                        (list 'if
  1567. X                          'n
  1568. X                          (list 'prefix-numeric-value
  1569. X                            'n)
  1570. X                          (nth 1 inter)))))
  1571. X                (list
  1572. X                 (list 'calc-enter-result
  1573. X                       (if hasmulti 'n (nth 1 inter))
  1574. X                       (nth 2 inter)
  1575. X                       (if hasprefix
  1576. X                       (list 'append
  1577. X                         (list 'quote (list fname))
  1578. X                         (list 'calc-top-list-n
  1579. X                               (nth 1 inter))
  1580. X                         (list 'and
  1581. X                               'n
  1582. X                               (list
  1583. X                            'list
  1584. X                            (list
  1585. X                             'math-normalize
  1586. X                             (list
  1587. X                              'prefix-numeric-value
  1588. X                              'n)))))
  1589. X                     (list 'cons
  1590. X                           (list 'quote fname)
  1591. X                           (list 'calc-top-list-n
  1592. X                             (if hasmulti
  1593. X                             'n
  1594. X                               (nth 1 inter)))))))))))
  1595. X          (append (list 'defun
  1596. X                (intern (concat "calc-" (symbol-name func)))
  1597. X                args)
  1598. X              doc
  1599. X              (list
  1600. X               inter
  1601. X               (cons 'calc-wrapper body))))))
  1602. X      (append (list 'defun fname clargs)
  1603. X          doc
  1604. X          (math-do-arg-list-check args nil nil)
  1605. X          body)))
  1606. X)
  1607. X
  1608. X(defun math-clean-arg (arg)
  1609. X  (if (consp arg)
  1610. X      (math-clean-arg (nth 1 arg))
  1611. X    arg)
  1612. X)
  1613. X
  1614. X(defun math-do-arg-check (arg var is-opt is-rest)
  1615. X  (if is-opt
  1616. X      (let ((chk (math-do-arg-check arg var nil nil)))
  1617. X    (list (cons 'and
  1618. X            (cons var
  1619. X              (if (cdr chk)
  1620. X                  (setq chk (list (cons 'progn chk)))
  1621. X                chk)))))
  1622. X    (and (consp arg)
  1623. X     (let* ((rest (math-do-arg-check (nth 1 arg) var is-opt is-rest))
  1624. X        (qual (car arg))
  1625. X        (qqual (list 'quote qual))
  1626. X        (qual-name (symbol-name qual))
  1627. X        (chk (intern (concat "math-check-" qual-name))))
  1628. X       (if (fboundp chk)
  1629. X           (append rest
  1630. X               (list
  1631. X            (if is-rest
  1632. X                (list 'setq var
  1633. X                  (list 'mapcar (list 'quote chk) var))
  1634. X              (list 'setq var (list chk var)))))
  1635. X         (if (fboundp (setq chk (intern (concat "math-" qual-name))))
  1636. X         (append rest
  1637. X             (list
  1638. X              (if is-rest
  1639. X                  (list 'mapcar
  1640. X                    (list 'function
  1641. X                      (list 'lambda '(x)
  1642. X                        (list 'or
  1643. X                              (list chk 'x)
  1644. X                              (list 'math-reject-arg
  1645. X                                'x qqual))))
  1646. X                    var)
  1647. X                (list 'or
  1648. X                  (list chk var)
  1649. X                  (list 'math-reject-arg var qqual)))))
  1650. X           (if (and (string-match "\\`not-\\(.*\\)\\'" qual-name)
  1651. X            (fboundp (setq chk (intern
  1652. X                        (concat "math-"
  1653. X                            (math-match-substring
  1654. X                             qual-name 1))))))
  1655. X           (append rest
  1656. X               (list
  1657. X                (if is-rest
  1658. X                (list 'mapcar
  1659. X                      (list 'function
  1660. X                        (list 'lambda '(x)
  1661. X                          (list 'and
  1662. X                            (list chk 'x)
  1663. X                            (list 'math-reject-arg
  1664. X                                  'x qqual))))
  1665. X                      var)
  1666. X                  (list 'and
  1667. X                    (list chk var)
  1668. X                    (list 'math-reject-arg var qqual)))))
  1669. X         (error "Unknown qualifier `%s'" qual-name)))))))
  1670. X)
  1671. X
  1672. X(defun math-do-arg-list-check (args is-opt is-rest)
  1673. X  (cond ((null args) nil)
  1674. X    ((consp (car args))
  1675. X     (append (math-do-arg-check (car args)
  1676. X                    (math-clean-arg (car args))
  1677. X                    is-opt is-rest)
  1678. X         (math-do-arg-list-check (cdr args) is-opt is-rest)))
  1679. X    ((eq (car args) '&optional)
  1680. X     (math-do-arg-list-check (cdr args) t nil))
  1681. X    ((eq (car args) '&rest)
  1682. X     (math-do-arg-list-check (cdr args) nil t))
  1683. X    (t (math-do-arg-list-check (cdr args) is-opt is-rest)))
  1684. X)
  1685. X
  1686. X(defconst math-prim-funcs
  1687. X  '( (~= . math-nearly-equal)
  1688. X     (% . math-mod)
  1689. X     (lsh . math-lshift-binary)
  1690. X     (ash . math-shift-binary)
  1691. X     (logand . math-and)
  1692. X     (logandc2 . math-diff)
  1693. X     (logior . math-or)
  1694. X     (logxor . math-xor)
  1695. X     (lognot . math-not)
  1696. X     (equal . equal)   ; need to leave these ones alone!
  1697. X     (eq . eq)
  1698. X     (and . and)
  1699. X     (or . or)
  1700. X     (if . if)
  1701. X     (^ . math-pow)
  1702. X     (expt . math-pow)
  1703. X   )
  1704. X)
  1705. X
  1706. X(defconst math-prim-vars
  1707. X  '( (nil . nil)
  1708. X     (t . t)
  1709. X     (&optional . &optional)
  1710. X     (&rest . &rest)
  1711. X   )
  1712. X)
  1713. X
  1714. X(defun math-define-function-body (body env)
  1715. X  (let ((body (math-define-body body env)))
  1716. X    (if (math-body-refers-to body 'math-return)
  1717. X    (list (cons 'catch (cons '(quote math-return) body)))
  1718. X      body))
  1719. X)
  1720. X
  1721. X(defun math-define-body (body exp-env)
  1722. X  (math-define-list body)
  1723. X)
  1724. X
  1725. X(defun math-define-list (body &optional quote)
  1726. X  (cond ((null body)
  1727. X     nil)
  1728. X    ((and (eq (car body) ':)
  1729. X          (stringp (nth 1 body)))
  1730. X     (cons (let* ((math-read-expr-quotes t)
  1731. X              (calc-language nil)
  1732. X              (math-expr-opers math-standard-opers)
  1733. X              (exp (math-read-expr (nth 1 body))))
  1734. X         (if (eq (car exp) 'error)
  1735. X             (error "Bad format: %s" (nth 1 body))
  1736. X           (math-define-exp exp)))
  1737. X           (math-define-list (cdr (cdr body)))))
  1738. X    (quote
  1739. X     (cons (cond ((consp (car body))
  1740. X              (math-define-list (cdr body) t))
  1741. X             (t
  1742. X              (car body)))
  1743. X           (math-define-list (cdr body))))
  1744. X    (t
  1745. X     (cons (math-define-exp (car body))
  1746. X           (math-define-list (cdr body)))))
  1747. X)
  1748. X
  1749. X(defun math-define-exp (exp)
  1750. X  (cond ((consp exp)
  1751. X     (let ((func (car exp)))
  1752. X       (cond ((memq func '(quote function))
  1753. X          (if (and (consp (nth 1 exp))
  1754. X               (eq (car (nth 1 exp)) 'lambda))
  1755. X              (cons 'quote
  1756. X                (math-define-lambda (nth 1 exp) exp-env))
  1757. X            exp))
  1758. X         ((memq func '(let let* for foreach))
  1759. X          (let ((head (nth 1 exp))
  1760. X            (body (cdr (cdr exp))))
  1761. X            (if (memq func '(let let*))
  1762. X            ()
  1763. X              (setq func (cdr (assq func '((for . math-for)
  1764. X                           (foreach . math-foreach)))))
  1765. X              (if (not (listp (car head)))
  1766. X              (setq head (list head))))
  1767. X            (macroexpand
  1768. X             (cons func
  1769. X               (cons (math-define-let head)
  1770. X                 (math-define-body body
  1771. X                           (nconc
  1772. X                            (math-define-let-env head)
  1773. X                            exp-env)))))))
  1774. X         ((and (memq func '(setq setf))
  1775. X               (math-complicated-lhs (cdr exp)))
  1776. X          (if (> (length exp) 3)
  1777. X              (cons 'progn (math-define-setf-list (cdr exp)))
  1778. X            (math-define-setf (nth 1 exp) (nth 2 exp))))
  1779. X         ((eq func 'condition-case)
  1780. X          (cons func
  1781. X            (cons (nth 1 exp)
  1782. X                  (math-define-body (cdr (cdr exp))
  1783. X                        (cons (nth 1 exp)
  1784. X                              exp-env)))))
  1785. X         ((eq func 'cond)
  1786. X          (cons func
  1787. X            (math-define-cond (cdr exp))))
  1788. X         ((and (consp func)   ; ('spam a b) == force use of plain spam
  1789. X               (eq (car func) 'quote))
  1790. X          (cons func (math-define-list (cdr exp))))
  1791. X         ((symbolp func)
  1792. X          (let ((args (math-define-list (cdr exp)))
  1793. X            (prim (assq func math-prim-funcs)))
  1794. X            (cond (prim
  1795. X               (cons (cdr prim) args))
  1796. X              ((eq func 'floatp)
  1797. X               (list 'eq (car args) '(quote float)))
  1798. X              ((eq func '+)
  1799. X               (math-define-binop 'math-add 0
  1800. X                          (car args) (cdr args)))
  1801. X              ((eq func '-)
  1802. X               (if (= (length args) 1)
  1803. X                   (cons 'math-neg args)
  1804. X                 (math-define-binop 'math-sub 0
  1805. X                        (car args) (cdr args))))
  1806. X              ((eq func '*)
  1807. X               (math-define-binop 'math-mul 1
  1808. X                          (car args) (cdr args)))
  1809. X              ((eq func '/)
  1810. X               (math-define-binop 'math-div 1
  1811. X                          (car args) (cdr args)))
  1812. X              ((eq func 'min)
  1813. X               (math-define-binop 'math-min 0
  1814. X                          (car args) (cdr args)))
  1815. X              ((eq func 'max)
  1816. X               (math-define-binop 'math-max 0
  1817. X                          (car args) (cdr args)))
  1818. X              ((eq func '<)
  1819. X               (if (and (math-numberp (nth 1 args))
  1820. X                    (math-zerop (nth 1 args)))
  1821. X                   (list 'math-posp (car args))
  1822. X                 (cons 'math-lessp args)))
  1823. X              ((eq func '>)
  1824. X               (if (and (math-numberp (nth 1 args))
  1825. X                    (math-zerop (nth 1 args)))
  1826. X                   (list 'math-posp (car args))
  1827. X                 (list 'math-lessp (nth 1 args) (nth 0 args))))
  1828. X              ((eq func '<=)
  1829. X               (list 'not
  1830. X                 (if (and (math-numberp (nth 1 args))
  1831. X                      (math-zerop (nth 1 args)))
  1832. X                     (list 'math-posp (car args))
  1833. X                   (cons 'math-lessp args))))
  1834. X              ((eq func '>=)
  1835. X               (list 'not
  1836. X                 (if (and (math-numberp (nth 1 args))
  1837. X                      (math-zerop (nth 1 args)))
  1838. X                     (list 'math-negp (car args))
  1839. X                   (list 'math-lessp
  1840. X                     (nth 1 args) (nth 0 args)))))
  1841. X              ((eq func '=)
  1842. X               (if (and (math-numberp (nth 1 args))
  1843. X                    (math-zerop (nth 1 args)))
  1844. X                   (list 'math-zerop (nth 0 args))
  1845. X                 (if (and (integerp (nth 1 args))
  1846. X                      (/= (% (nth 1 args) 10) 0))
  1847. X                 (cons 'math-equal-int args)
  1848. X                   (cons 'math-equal args))))
  1849. X              ((eq func '/=)
  1850. X               (list 'not
  1851. X                 (if (and (math-numberp (nth 1 args))
  1852. X                      (math-zerop (nth 1 args)))
  1853. X                     (list 'math-zerop (nth 0 args))
  1854. X                   (if (and (integerp (nth 1 args))
  1855. X                        (/= (% (nth 1 args) 10) 0))
  1856. X                       (cons 'math-equal-int args)
  1857. X                     (cons 'math-equal args)))))
  1858. X              ((eq func '1+)
  1859. X               (list 'math-add (car args) 1))
  1860. X              ((eq func '1-)
  1861. X               (list 'math-add (car args) -1))
  1862. X              ((eq func 'not)   ; optimize (not (not x)) => x
  1863. X               (if (eq (car-safe args) func)
  1864. X                   (car (nth 1 args))
  1865. X                 (cons func args)))
  1866. X              ((and (eq func 'elt) (cdr (cdr args)))
  1867. X               (math-define-elt (car args) (cdr args)))
  1868. X              (t
  1869. X               (macroexpand
  1870. X                (let* ((name (symbol-name func))
  1871. X                   (cfunc (intern (concat "calcFunc-" name)))
  1872. X                   (mfunc (intern (concat "math-" name))))
  1873. X                  (cond ((fboundp cfunc)
  1874. X                     (cons cfunc args))
  1875. X                    ((fboundp mfunc)
  1876. X                     (cons mfunc args))
  1877. X                    ((or (fboundp func)
  1878. X                     (string-match "\\`calcFunc-.*" name))
  1879. X                     (cons func args))
  1880. X                    (t
  1881. X                     (cons cfunc args)))))))))
  1882. X         (t (cons func args)))))
  1883. X    ((symbolp exp)
  1884. X     (let ((prim (assq exp math-prim-vars))
  1885. X           (name (symbol-name exp)))
  1886. X       (cond (prim
  1887. X          (cdr prim))
  1888. X         ((memq exp exp-env)
  1889. X          exp)
  1890. X         ((string-match "-" name)
  1891. SHAR_EOF
  1892. echo "End of part 10"
  1893. echo "File calc-ext.el is continued in part 11"
  1894. echo "11" > s2_seq_.tmp
  1895. exit 0
  1896.