home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume24 / gnucalc / part23 < prev    next >
Encoding:
Text File  |  1991-10-31  |  55.2 KB  |  1,823 lines

  1. Newsgroups: comp.sources.misc
  2. From: daveg@synaptics.com (David Gillespie)
  3. Subject:  v24i071:  gnucalc - GNU Emacs Calculator, v2.00, Part23/56
  4. Message-ID: <1991Oct31.072724.18108@sparky.imd.sterling.com>
  5. X-Md4-Signature: c38f6be13094468a0ba909ef5925764e
  6. Date: Thu, 31 Oct 1991 07:27:24 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: daveg@synaptics.com (David Gillespie)
  10. Posting-number: Volume 24, Issue 71
  11. Archive-name: gnucalc/part23
  12. Environment: Emacs
  13. Supersedes: gmcalc: Volume 13, Issue 27-45
  14.  
  15. ---- Cut Here and unpack ----
  16. #!/bin/sh
  17. # do not concatenate these parts, unpack them in order with /bin/sh
  18. # file calc-poly.el continued
  19. #
  20. if test ! -r _shar_seq_.tmp; then
  21.     echo 'Please unpack part 1 first!'
  22.     exit 1
  23. fi
  24. (read Scheck
  25.  if test "$Scheck" != 23; then
  26.     echo Please unpack part "$Scheck" next!
  27.     exit 1
  28.  else
  29.     exit 0
  30.  fi
  31. ) < _shar_seq_.tmp || exit 1
  32. if test ! -f _shar_wnt_.tmp; then
  33.     echo 'x - still skipping calc-poly.el'
  34. else
  35. echo 'x - continuing file calc-poly.el'
  36. sed 's/^X//' << 'SHAR_EOF' >> 'calc-poly.el' &&
  37. )
  38. X
  39. X
  40. ;;; Multiply two terms, expanding out products of sums.
  41. (defun math-mul-thru (lhs rhs)
  42. X  (if (memq (car-safe lhs) '(+ -))
  43. X      (list (car lhs)
  44. X        (math-mul-thru (nth 1 lhs) rhs)
  45. X        (math-mul-thru (nth 2 lhs) rhs))
  46. X    (if (memq (car-safe rhs) '(+ -))
  47. X    (list (car rhs)
  48. X          (math-mul-thru lhs (nth 1 rhs))
  49. X          (math-mul-thru lhs (nth 2 rhs)))
  50. X      (math-mul lhs rhs)))
  51. )
  52. X
  53. (defun math-div-thru (num den)
  54. X  (if (memq (car-safe num) '(+ -))
  55. X      (list (car num)
  56. X        (math-div-thru (nth 1 num) den)
  57. X        (math-div-thru (nth 2 num) den))
  58. X    (math-div num den))
  59. )
  60. X
  61. X
  62. ;;; Sort the terms of a sum into canonical order.
  63. (defun math-sort-terms (expr)
  64. X  (if (memq (car-safe expr) '(+ -))
  65. X      (math-list-to-sum
  66. X       (sort (math-sum-to-list expr)
  67. X         (function (lambda (a b) (math-beforep (car a) (car b))))))
  68. X    expr)
  69. )
  70. X
  71. (defun math-list-to-sum (lst)
  72. X  (if (cdr lst)
  73. X      (list (if (cdr (car lst)) '- '+)
  74. X        (math-list-to-sum (cdr lst))
  75. X        (car (car lst)))
  76. X    (if (cdr (car lst))
  77. X    (math-neg (car (car lst)))
  78. X      (car (car lst))))
  79. )
  80. X
  81. (defun math-sum-to-list (tree &optional neg)
  82. X  (cond ((eq (car-safe tree) '+)
  83. X     (nconc (math-sum-to-list (nth 1 tree) neg)
  84. X        (math-sum-to-list (nth 2 tree) neg)))
  85. X    ((eq (car-safe tree) '-)
  86. X     (nconc (math-sum-to-list (nth 1 tree) neg)
  87. X        (math-sum-to-list (nth 2 tree) (not neg))))
  88. X    (t (list (cons tree neg))))
  89. )
  90. X
  91. ;;; Check if the polynomial coefficients are modulo forms.
  92. (defun math-poly-modulus (expr &optional expr2)
  93. X  (or (math-poly-modulus-rec expr)
  94. X      (and expr2 (math-poly-modulus-rec expr2))
  95. X      1)
  96. )
  97. X
  98. (defun math-poly-modulus-rec (expr)
  99. X  (if (and (eq (car-safe expr) 'mod) (Math-natnump (nth 2 expr)))
  100. X      (list 'mod 1 (nth 2 expr))
  101. X    (and (memq (car-safe expr) '(+ - * /))
  102. X     (or (math-poly-modulus-rec (nth 1 expr))
  103. X         (math-poly-modulus-rec (nth 2 expr)))))
  104. )
  105. X
  106. X
  107. ;;; Divide two polynomials.  Return (quotient . remainder).
  108. (defun math-poly-div (u v &optional math-poly-div-base)
  109. X  (if math-poly-div-base
  110. X      (math-do-poly-div u v)
  111. X    (math-do-poly-div (calcFunc-expand u) (calcFunc-expand v)))
  112. )
  113. (setq math-poly-div-base nil)
  114. X
  115. (defun math-poly-div-exact (u v &optional base)
  116. X  (let ((res (math-poly-div u v base)))
  117. X    (if (eq (cdr res) 0)
  118. X    (car res)
  119. X      (math-reject-arg (list 'vec u v) "Argument is not a polynomial")))
  120. )
  121. X
  122. (defun math-do-poly-div (u v)
  123. X  (cond ((math-constp u)
  124. X     (if (math-constp v)
  125. X         (cons (math-div u v) 0)
  126. X       (cons 0 u)))
  127. X    ((math-constp v)
  128. X     (cons (if (eq v 1)
  129. X           u
  130. X         (if (memq (car-safe u) '(+ -))
  131. X             (math-add-or-sub (math-poly-div-exact (nth 1 u) v)
  132. X                      (math-poly-div-exact (nth 2 u) v)
  133. X                      nil (eq (car u) '-))
  134. X           (math-div u v)))
  135. X           0))
  136. X    ((Math-equal u v)
  137. X     (cons math-poly-modulus 0))
  138. X    ((and (math-atomic-factorp u) (math-atomic-factorp v))
  139. X     (cons (math-simplify (math-div u v)) 0))
  140. X    (t
  141. X     (let ((base (or math-poly-div-base
  142. X             (math-poly-div-base u v)))
  143. X           vp up res)
  144. X       (if (or (null base)
  145. X           (null (setq vp (math-is-polynomial v base nil 'gen))))
  146. X           (cons 0 u)
  147. X         (setq up (math-is-polynomial u base nil 'gen)
  148. X           res (math-poly-div-coefs up vp))
  149. X         (cons (math-build-polynomial-expr (car res) base)
  150. X           (math-build-polynomial-expr (cdr res) base))))))
  151. )
  152. X
  153. (defun math-poly-div-rec (u v)
  154. X  (cond ((math-constp u)
  155. X     (math-div u v))
  156. X    ((math-constp v)
  157. X     (if (eq v 1)
  158. X         u
  159. X       (if (memq (car-safe u) '(+ -))
  160. X           (math-add-or-sub (math-poly-div-rec (nth 1 u) v)
  161. X                (math-poly-div-rec (nth 2 u) v)
  162. X                nil (eq (car u) '-))
  163. X         (math-div u v))))
  164. X    ((Math-equal u v) math-poly-modulus)
  165. X    ((and (math-atomic-factorp u) (math-atomic-factorp v))
  166. X     (math-simplify (math-div u v)))
  167. X    (math-poly-div-base
  168. X     (math-div u v))
  169. X    (t
  170. X     (let ((base (math-poly-div-base u v))
  171. X           vp up res)
  172. X       (if (or (null base)
  173. X           (null (setq vp (math-is-polynomial v base nil 'gen))))
  174. X           (math-div u v)
  175. X         (setq up (math-is-polynomial u base nil 'gen)
  176. X           res (math-poly-div-coefs up vp))
  177. X         (math-add (math-build-polynomial-expr (car res) base)
  178. X               (math-div (math-build-polynomial-expr (cdr res) base)
  179. X                 v))))))
  180. )
  181. X
  182. ;;; Divide two polynomials in coefficient-list form.  Return (quot . rem).
  183. (defun math-poly-div-coefs (u v)
  184. X  (cond ((null v) (math-reject-arg nil "Division by zero"))
  185. X    ((< (length u) (length v)) (cons nil u))
  186. X    ((cdr u)
  187. X     (let ((q nil)
  188. X           (urev (reverse u))
  189. X           (vrev (reverse v)))
  190. X       (while
  191. X           (let ((qk (math-poly-div-rec (math-simplify (car urev))
  192. X                        (car vrev)))
  193. X             (up urev)
  194. X             (vp vrev))
  195. X         (if (or q (not (math-zerop qk)))
  196. X             (setq q (cons qk q)))
  197. X         (while (setq up (cdr up) vp (cdr vp))
  198. X           (setcar up (math-sub (car up) (math-mul-thru qk (car vp)))))
  199. X         (setq urev (cdr urev))
  200. X         up))
  201. X       (while (and urev (Math-zerop (car urev)))
  202. X         (setq urev (cdr urev)))
  203. X       (cons q (nreverse (mapcar 'math-simplify urev)))))
  204. X    (t
  205. X     (cons (list (math-poly-div-rec (car u) (car v)))
  206. X           nil)))
  207. )
  208. X
  209. ;;; Perform a pseudo-division of polynomials.  (See Knuth section 4.6.1.)
  210. ;;; This returns only the remainder from the pseudo-division.
  211. (defun math-poly-pseudo-div (u v)
  212. X  (cond ((null v) nil)
  213. X    ((< (length u) (length v)) u)
  214. X    ((or (cdr u) (cdr v))
  215. X     (let ((urev (reverse u))
  216. X           (vrev (reverse v))
  217. X           up)
  218. X       (while
  219. X           (let ((vp vrev))
  220. X         (setq up urev)
  221. X         (while (setq up (cdr up) vp (cdr vp))
  222. X           (setcar up (math-sub (math-mul-thru (car vrev) (car up))
  223. X                    (math-mul-thru (car urev) (car vp)))))
  224. X         (setq urev (cdr urev))
  225. X         up)
  226. X         (while up
  227. X           (setcar up (math-mul-thru (car vrev) (car up)))
  228. X           (setq up (cdr up))))
  229. X       (while (and urev (Math-zerop (car urev)))
  230. X         (setq urev (cdr urev)))
  231. X       (nreverse (mapcar 'math-simplify urev))))
  232. X    (t nil))
  233. )
  234. X
  235. ;;; Compute the GCD of two multivariate polynomials.
  236. (defun math-poly-gcd (u v)
  237. X  (cond ((Math-equal u v) u)
  238. X    ((math-constp u)
  239. X     (if (Math-zerop u)
  240. X         v
  241. X       (calcFunc-gcd u (calcFunc-pcont v))))
  242. X    ((math-constp v)
  243. X     (if (Math-zerop v)
  244. X         v
  245. X       (calcFunc-gcd v (calcFunc-pcont u))))
  246. X    (t
  247. X     (let ((base (math-poly-gcd-base u v)))
  248. X       (if base
  249. X           (math-simplify
  250. X        (calcFunc-expand
  251. X         (math-build-polynomial-expr
  252. X          (math-poly-gcd-coefs (math-is-polynomial u base nil 'gen)
  253. X                       (math-is-polynomial v base nil 'gen))
  254. X          base)))
  255. X         (calcFunc-gcd (calcFunc-pcont u) (calcFunc-pcont u))))))
  256. )
  257. X
  258. (defun math-poly-div-list (lst a)
  259. X  (if (eq a 1)
  260. X      lst
  261. X    (if (eq a -1)
  262. X    (math-mul-list lst a)
  263. X      (mapcar (function (lambda (x) (math-poly-div-exact x a))) lst)))
  264. )
  265. X
  266. (defun math-mul-list (lst a)
  267. X  (if (eq a 1)
  268. X      lst
  269. X    (if (eq a -1)
  270. X    (mapcar 'math-neg lst)
  271. X      (and (not (eq a 0))
  272. X       (mapcar (function (lambda (x) (math-mul x a))) lst))))
  273. )
  274. X
  275. ;;; Run GCD on all elements in a list.
  276. (defun math-poly-gcd-list (lst)
  277. X  (if (or (memq 1 lst) (memq -1 lst))
  278. X      (math-poly-gcd-frac-list lst)
  279. X    (let ((gcd (car lst)))
  280. X      (while (and (setq lst (cdr lst)) (not (eq gcd 1)))
  281. X    (or (eq (car lst) 0)
  282. X        (setq gcd (math-poly-gcd gcd (car lst)))))
  283. X      (if lst (setq lst (math-poly-gcd-frac-list lst)))
  284. X      gcd))
  285. )
  286. X
  287. (defun math-poly-gcd-frac-list (lst)
  288. X  (while (and lst (not (eq (car-safe (car lst)) 'frac)))
  289. X    (setq lst (cdr lst)))
  290. X  (if lst
  291. X      (let ((denom (nth 2 (car lst))))
  292. X    (while (setq lst (cdr lst))
  293. X      (if (eq (car-safe (car lst)) 'frac)
  294. X          (setq denom (calcFunc-lcm denom (nth 2 (car lst))))))
  295. X    (list 'frac 1 denom))
  296. X    1)
  297. )
  298. X
  299. ;;; Compute the GCD of two monovariate polynomial lists.
  300. ;;; Knuth section 4.6.1, algorithm C.
  301. (defun math-poly-gcd-coefs (u v)
  302. X  (let ((d (math-poly-gcd (math-poly-gcd-list u)
  303. X              (math-poly-gcd-list v)))
  304. X    (g 1) (h 1) (z 0) hh r delta ghd)
  305. X    (while (and u v (Math-zerop (car u)) (Math-zerop (car v)))
  306. X      (setq u (cdr u) v (cdr v) z (1+ z)))
  307. X    (or (eq d 1)
  308. X    (setq u (math-poly-div-list u d)
  309. X          v (math-poly-div-list v d)))
  310. X    (while (progn
  311. X         (setq delta (- (length u) (length v)))
  312. X         (if (< delta 0)
  313. X         (setq r u u v v r delta (- delta)))
  314. X         (setq r (math-poly-pseudo-div u v))
  315. X         (cdr r))
  316. X      (setq u v
  317. X        v (math-poly-div-list r (math-mul g (math-pow h delta)))
  318. X        g (nth (1- (length u)) u)
  319. X        h (if (<= delta 1)
  320. X          (math-mul (math-pow g delta) (math-pow h (- 1 delta)))
  321. X        (math-poly-div-exact (math-pow g delta)
  322. X                     (math-pow h (1- delta))))))
  323. X    (setq v (if r
  324. X        (list d)
  325. X          (math-mul-list (math-poly-div-list v (math-poly-gcd-list v)) d)))
  326. X    (if (math-guess-if-neg (nth (1- (length v)) v))
  327. X    (setq v (math-mul-list v -1)))
  328. X    (while (>= (setq z (1- z)) 0)
  329. X      (setq v (cons 0 v)))
  330. X    v)
  331. )
  332. X
  333. X
  334. ;;; Return true if is a factor containing no sums or quotients.
  335. (defun math-atomic-factorp (expr)
  336. X  (cond ((eq (car-safe expr) '*)
  337. X     (and (math-atomic-factorp (nth 1 expr))
  338. X          (math-atomic-factorp (nth 2 expr))))
  339. X    ((memq (car-safe expr) '(+ - /))
  340. X     nil)
  341. X    ((memq (car-safe expr) '(^ neg))
  342. X     (math-atomic-factorp (nth 1 expr)))
  343. X    (t t))
  344. )
  345. X
  346. ;;; Find a suitable base for dividing a by b.
  347. ;;; The base must exist in both expressions.
  348. ;;; The degree in the numerator must be higher or equal than the
  349. ;;; degree in the denominator.
  350. ;;; If the above conditions are not met the quotient is just a remainder.
  351. ;;; Return nil if this is the case.
  352. X
  353. (defun math-poly-div-base (a b)
  354. X  (let (a-base b-base)
  355. X    (and (setq a-base (math-total-polynomial-base a))
  356. X     (setq b-base (math-total-polynomial-base b))
  357. X     (catch 'return
  358. X       (while a-base
  359. X         (let ((maybe (assoc (car (car a-base)) b-base)))
  360. X           (if maybe
  361. X           (if (>= (nth 1 (car a-base)) (nth 1 maybe))
  362. X               (throw 'return (car (car a-base))))))
  363. X         (setq a-base (cdr a-base))))))
  364. )
  365. X
  366. ;;; Same as above but for gcd algorithm.
  367. ;;; Here there is no requirement that degree(a) > degree(b).
  368. ;;; Take the base that has the highest degree considering both a and b.
  369. ;;; ("a^20+b^21+x^3+a+b", "a+b^2+x^5+a^22+b^10") --> (a 22)
  370. X
  371. (defun math-poly-gcd-base (a b)
  372. X  (let (a-base b-base)
  373. X    (and (setq a-base (math-total-polynomial-base a))
  374. X     (setq b-base (math-total-polynomial-base b))
  375. X     (catch 'return
  376. X       (while (and a-base b-base)
  377. X         (if (> (nth 1 (car a-base)) (nth 1 (car b-base)))
  378. X         (if (assoc (car (car a-base)) b-base)
  379. X             (throw 'return (car (car a-base)))
  380. X           (setq a-base (cdr a-base)))
  381. X           (if (assoc (car (car b-base)) a-base)
  382. X           (throw 'return (car (car b-base)))
  383. X         (setq b-base (cdr b-base))))))))
  384. )
  385. X
  386. ;;; Sort a list of polynomial bases.
  387. (defun math-sort-poly-base-list (lst)
  388. X  (sort lst (function (lambda (a b)
  389. X            (or (> (nth 1 a) (nth 1 b))
  390. X                (and (= (nth 1 a) (nth 1 b))
  391. X                 (math-beforep (car a) (car b)))))))
  392. )
  393. X
  394. ;;; Given an expression find all variables that are polynomial bases.
  395. ;;; Return list in the form '( (var1 degree1) (var2 degree2) ... ).
  396. ;;; Note dynamic scope of mpb-total-base.
  397. (defun math-total-polynomial-base (expr)
  398. X  (let ((mpb-total-base nil))
  399. X    (math-polynomial-base expr 'math-polynomial-p1)
  400. X    (math-sort-poly-base-list mpb-total-base))
  401. )
  402. X
  403. (defun math-polynomial-p1 (subexpr)
  404. X  (or (assoc subexpr mpb-total-base)
  405. X      (memq (car subexpr) '(+ - * / neg))
  406. X      (and (eq (car subexpr) '^) (natnump (nth 2 subexpr)))
  407. X      (let* ((math-poly-base-variable subexpr)
  408. X         (exponent (math-polynomial-p mpb-top-expr subexpr)))
  409. X    (if exponent
  410. X        (setq mpb-total-base (cons (list subexpr exponent)
  411. X                       mpb-total-base)))))
  412. X  nil
  413. )
  414. X
  415. X
  416. X
  417. X
  418. (defun calcFunc-factors (expr &optional var)
  419. X  (let ((math-factored-vars (if var t nil))
  420. X    (math-to-list t)
  421. X    (calc-prefer-frac t))
  422. X    (or var
  423. X    (setq var (math-polynomial-base expr)))
  424. X    (let ((res (math-factor-finish
  425. X        (or (catch 'factor (math-factor-expr-try var))
  426. X            expr))))
  427. X      (math-simplify (if (math-vectorp res)
  428. X             res
  429. X               (list 'vec (list 'vec res 1))))))
  430. )
  431. X
  432. (defun calcFunc-factor (expr &optional var)
  433. X  (let ((math-factored-vars nil)
  434. X    (math-to-list nil)
  435. X    (calc-prefer-frac t))
  436. X    (math-simplify (math-factor-finish
  437. X            (if var
  438. X            (let ((math-factored-vars t))
  439. X              (or (catch 'factor (math-factor-expr-try var)) expr))
  440. X              (math-factor-expr expr)))))
  441. )
  442. X
  443. (defun math-factor-finish (x)
  444. X  (if (Math-primp x)
  445. X      x
  446. X    (if (eq (car x) 'calcFunc-Fac-Prot)
  447. X    (math-factor-finish (nth 1 x))
  448. X      (cons (car x) (mapcar 'math-factor-finish (cdr x)))))
  449. )
  450. X
  451. (defun math-factor-protect (x)
  452. X  (if (memq (car-safe x) '(+ -))
  453. X      (list 'calcFunc-Fac-Prot x)
  454. X    x)
  455. )
  456. X
  457. (defun math-factor-expr (expr)
  458. X  (cond ((eq math-factored-vars t) expr)
  459. X    ((or (memq (car-safe expr) '(* / ^ neg))
  460. X         (assq (car-safe expr) calc-tweak-eqn-table))
  461. X     (cons (car expr) (mapcar 'math-factor-expr (cdr expr))))
  462. X    ((memq (car-safe expr) '(+ -))
  463. X     (let* ((math-factored-vars math-factored-vars)
  464. X        (y (catch 'factor (math-factor-expr-part expr))))
  465. X       (if y
  466. X           (math-factor-expr y)
  467. X         expr)))
  468. X    (t expr))
  469. )
  470. X
  471. (defun math-factor-expr-part (x)    ; uses "expr"
  472. X  (if (memq (car-safe x) '(+ - * / ^ neg))
  473. X      (while (setq x (cdr x))
  474. X    (math-factor-expr-part (car x)))
  475. X    (and (not (Math-objvecp x))
  476. X     (not (assoc x math-factored-vars))
  477. X     (> (math-factor-contains expr x) 1)
  478. X     (setq math-factored-vars (cons (list x) math-factored-vars))
  479. X     (math-factor-expr-try x)))
  480. )
  481. X
  482. (defun math-factor-expr-try (x)
  483. X  (if (eq (car-safe expr) '*)
  484. X      (let ((res1 (catch 'factor (let ((expr (nth 1 expr)))
  485. X                   (math-factor-expr-try x))))
  486. X        (res2 (catch 'factor (let ((expr (nth 2 expr)))
  487. X                   (math-factor-expr-try x)))))
  488. X    (and (or res1 res2)
  489. X         (throw 'factor (math-accum-factors (or res1 (nth 1 expr)) 1
  490. X                        (or res2 (nth 2 expr))))))
  491. X    (let* ((p (math-is-polynomial expr x 30 'gen))
  492. X       (math-poly-modulus (math-poly-modulus expr))
  493. X       res)
  494. X      (and (cdr p)
  495. X       (setq res (math-factor-poly-coefs p))
  496. X       (throw 'factor res))))
  497. )
  498. X
  499. (defun math-accum-factors (fac pow facs)
  500. X  (if math-to-list
  501. X      (if (math-vectorp fac)
  502. X      (progn
  503. X        (while (setq fac (cdr fac))
  504. X          (setq facs (math-accum-factors (nth 1 (car fac))
  505. X                         (* pow (nth 2 (car fac)))
  506. X                         facs)))
  507. X        facs)
  508. X    (if (and (eq (car-safe fac) '^) (natnump (nth 2 fac)))
  509. X        (setq pow (* pow (nth 2 fac))
  510. X          fac (nth 1 fac)))
  511. X    (if (eq fac 1)
  512. X        facs
  513. X      (or (math-vectorp facs)
  514. X          (setq facs (if (eq facs 1) '(vec)
  515. X               (list 'vec (list 'vec facs 1)))))
  516. X      (let ((found facs))
  517. X        (while (and (setq found (cdr found))
  518. X            (not (equal fac (nth 1 (car found))))))
  519. X        (if found
  520. X        (progn
  521. X          (setcar (cdr (cdr (car found))) (+ pow (nth 2 (car found))))
  522. X          facs)
  523. X          ;; Put constant term first.
  524. X          (if (and (cdr facs) (Math-ratp (nth 1 (nth 1 facs))))
  525. X          (cons 'vec (cons (nth 1 facs) (cons (list 'vec fac pow)
  526. X                              (cdr (cdr facs)))))
  527. X        (cons 'vec (cons (list 'vec fac pow) (cdr facs))))))))
  528. X    (math-mul (math-pow fac pow) facs))
  529. )
  530. X
  531. (defun math-factor-poly-coefs (p &optional square-free)    ; uses "x"
  532. X  (let (t1 t2)
  533. X    (cond ((not (cdr p))
  534. X       (or (car p) 0))
  535. X
  536. X      ;; Strip off multiples of x.
  537. X      ((Math-zerop (car p))
  538. X       (let ((z 0))
  539. X         (while (and p (Math-zerop (car p)))
  540. X           (setq z (1+ z) p (cdr p)))
  541. X         (if (cdr p)
  542. X         (setq p (math-factor-poly-coefs p square-free))
  543. X           (setq p (math-sort-terms (math-factor-expr (car p)))))
  544. X         (math-accum-factors x z (math-factor-protect p))))
  545. X
  546. X      ;; Factor out content.
  547. X      ((and (not square-free)
  548. X        (not (eq 1 (setq t1 (math-mul (math-poly-gcd-list p)
  549. X                          (if (math-guess-if-neg
  550. X                           (nth (1- (length p)) p))
  551. X                          -1 1))))))
  552. X       (math-accum-factors t1 1 (math-factor-poly-coefs
  553. X                     (math-poly-div-list p t1) 'cont)))
  554. X
  555. X      ;; Check if linear in x.
  556. X      ((not (cdr (cdr p)))
  557. X       (math-add (math-factor-protect
  558. X              (math-sort-terms
  559. X               (math-factor-expr (car p))))
  560. X             (math-mul x (math-factor-protect
  561. X                  (math-sort-terms
  562. X                   (math-factor-expr (nth 1 p)))))))
  563. X
  564. X      ;; If symbolic coefficients, use FactorRules.
  565. X      ((let ((pp p))
  566. X         (while (and pp (or (Math-ratp (car pp))
  567. X                (and (eq (car (car pp)) 'mod)
  568. X                     (Math-integerp (nth 1 (car pp)))
  569. X                     (Math-integerp (nth 2 (car pp))))))
  570. X           (setq pp (cdr pp)))
  571. X         pp)
  572. X       (let ((res (math-rewrite
  573. X               (list 'calcFunc-thecoefs x (cons 'vec p))
  574. X               '(var FactorRules var-FactorRules))))
  575. X         (or (and (eq (car-safe res) 'calcFunc-thefactors)
  576. X              (= (length res) 3)
  577. X              (math-vectorp (nth 2 res))
  578. X              (let ((facs 1)
  579. X                (vec (nth 2 res)))
  580. X            (while (setq vec (cdr vec))
  581. X              (setq facs (math-accum-factors (car vec) 1 facs)))
  582. X            facs))
  583. X         (math-build-polynomial-expr p x))))
  584. X
  585. X      ;; Check if rational coefficients (i.e., not modulo a prime).
  586. X      ((eq math-poly-modulus 1)
  587. X
  588. X       ;; Check if there are any squared terms, or a content not = 1.
  589. X       (if (or (eq square-free t)
  590. X           (equal (setq t1 (math-poly-gcd-coefs
  591. X                    p (setq t2 (math-poly-deriv-coefs p))))
  592. X              '(1)))
  593. X
  594. X           ;; We now have a square-free polynomial with integer coefs.
  595. X           ;; For now, we use a kludgey method that finds linear and
  596. X           ;; quadratic terms using floating-point root-finding.
  597. X           (if (setq t1 (let ((calc-symbolic-mode nil))
  598. X                  (math-poly-all-roots nil p t)))
  599. X           (let ((roots (car t1))
  600. X             (csign (if (math-negp (nth (1- (length p)) p)) -1 1))
  601. X             (expr 1)
  602. X             (unfac (nth 1 t1))
  603. X             (scale (nth 2 t1)))
  604. X             (while roots
  605. X               (let ((coef0 (car (car roots)))
  606. X                 (coef1 (cdr (car roots))))
  607. X             (setq expr (math-accum-factors
  608. X                     (if coef1
  609. X                     (let ((den (math-lcm-denoms
  610. X                             coef0 coef1)))
  611. X                       (setq scale (math-div scale den))
  612. X                       (math-add
  613. X                        (math-add
  614. X                         (math-mul den (math-pow x 2))
  615. X                         (math-mul (math-mul coef1 den) x))
  616. X                        (math-mul coef0 den)))
  617. X                       (let ((den (math-lcm-denoms coef0)))
  618. X                     (setq scale (math-div scale den))
  619. X                     (math-add (math-mul den x)
  620. X                           (math-mul coef0 den))))
  621. X                     1 expr)
  622. X                   roots (cdr roots))))
  623. X             (setq expr (math-accum-factors
  624. X                 expr 1
  625. X                 (math-mul csign
  626. X                       (math-build-polynomial-expr
  627. X                        (math-mul-list (nth 1 t1) scale)
  628. X                        x)))))
  629. X         (math-build-polynomial-expr p x))   ; can't factor it.
  630. X
  631. X         ;; Separate out the squared terms (Knuth exercise 4.6.2-34).
  632. X         ;; This step also divides out the content of the polynomial.
  633. X         (let* ((cabs (math-poly-gcd-list p))
  634. X            (csign (if (math-negp (nth (1- (length p)) p)) -1 1))
  635. X            (t1s (math-mul-list t1 csign))
  636. X            (uu nil)
  637. X            (v (car (math-poly-div-coefs p t1s)))
  638. X            (w (car (math-poly-div-coefs t2 t1s))))
  639. X           (while
  640. X           (not (math-poly-zerop
  641. X             (setq t2 (math-poly-simplify
  642. X                   (math-poly-mix
  643. X                    w 1 (math-poly-deriv-coefs v) -1)))))
  644. X         (setq t1 (math-poly-gcd-coefs v t2)
  645. X               uu (cons t1 uu)
  646. X               v (car (math-poly-div-coefs v t1))
  647. X               w (car (math-poly-div-coefs t2 t1))))
  648. X           (setq t1 (length uu)
  649. X             t2 (math-accum-factors (math-factor-poly-coefs v t)
  650. X                        (1+ t1) 1))
  651. X           (while uu
  652. X         (setq t2 (math-accum-factors (math-factor-poly-coefs
  653. X                           (car uu) t)
  654. X                          t1 t2)
  655. X               t1 (1- t1)
  656. X               uu (cdr uu)))
  657. X           (math-accum-factors (math-mul cabs csign) 1 t2))))
  658. X
  659. X      ;; Factoring modulo a prime.
  660. X      ((and (= (length (setq temp (math-poly-gcd-coefs
  661. X                       p (math-poly-deriv-coefs p))))
  662. X           (length p)))
  663. X       (setq p (car temp))
  664. X       (while (cdr temp)
  665. X         (setq temp (nthcdr (nth 2 math-poly-modulus) temp)
  666. X           p (cons (car temp) p)))
  667. X       (and (setq temp (math-factor-poly-coefs p))
  668. X        (math-pow temp (nth 2 math-poly-modulus))))
  669. X      (t
  670. X       (math-reject-arg nil "*Modulo factorization not yet implemented"))))
  671. )
  672. X
  673. (defun math-poly-deriv-coefs (p)
  674. X  (let ((n 1)
  675. X    (dp nil))
  676. X    (while (setq p (cdr p))
  677. X      (setq dp (cons (math-mul (car p) n) dp)
  678. X        n (1+ n)))
  679. X    (nreverse dp))
  680. )
  681. X
  682. (defun math-factor-contains (x a)
  683. X  (if (equal x a)
  684. X      1
  685. X    (if (memq (car-safe x) '(+ - * / neg))
  686. X    (let ((sum 0))
  687. X      (while (setq x (cdr x))
  688. X        (setq sum (+ sum (math-factor-contains (car x) a))))
  689. X      sum)
  690. X      (if (and (eq (car-safe x) '^)
  691. X           (natnump (nth 2 x)))
  692. X      (* (math-factor-contains (nth 1 x) a) (nth 2 x))
  693. X    0)))
  694. )
  695. X
  696. X
  697. X
  698. X
  699. X
  700. ;;; Merge all quotients and expand/simplify the numerator
  701. (defun calcFunc-nrat (expr)
  702. X  (if (math-any-floats expr)
  703. X      (setq expr (calcFunc-pfrac expr)))
  704. X  (if (math-vectorp expr)
  705. X      (cons 'vec (mapcar 'calcFunc-nrat (cdr expr)))
  706. X    (let* ((calc-prefer-frac t)
  707. X       (res (math-to-ratpoly expr))
  708. X       (num (math-simplify (math-sort-terms (calcFunc-expand (car res)))))
  709. X       (den (math-simplify (math-sort-terms (calcFunc-expand (cdr res)))))
  710. X       (g (math-poly-gcd num den)))
  711. X      (or (eq g 1)
  712. X      (let ((num2 (math-poly-div num g))
  713. X        (den2 (math-poly-div den g)))
  714. X        (and (eq (cdr num2) 0) (eq (cdr den2) 0)
  715. X         (setq num (car num2) den (car den2)))))
  716. X      (math-simplify (math-div num den))))
  717. )
  718. X
  719. ;;; Returns expressions (num . denom).
  720. (defun math-to-ratpoly (expr)
  721. X  (let ((res (math-to-ratpoly-rec expr)))
  722. X    (cons (math-simplify (car res)) (math-simplify (cdr res))))
  723. )
  724. X
  725. (defun math-to-ratpoly-rec (expr)
  726. X  (cond ((Math-primp expr)
  727. X     (cons expr 1))
  728. X    ((memq (car expr) '(+ -))
  729. X     (let ((r1 (math-to-ratpoly-rec (nth 1 expr)))
  730. X           (r2 (math-to-ratpoly-rec (nth 2 expr))))
  731. X       (if (equal (cdr r1) (cdr r2))
  732. X           (cons (list (car expr) (car r1) (car r2)) (cdr r1))
  733. X         (if (eq (cdr r1) 1)
  734. X         (cons (list (car expr)
  735. X                 (math-mul (car r1) (cdr r2))
  736. X                 (car r2))
  737. X               (cdr r2))
  738. X           (if (eq (cdr r2) 1)
  739. X           (cons (list (car expr)
  740. X                   (car r1)
  741. X                   (math-mul (car r2) (cdr r1)))
  742. X             (cdr r1))
  743. X         (let ((g (math-poly-gcd (cdr r1) (cdr r2))))
  744. X           (let ((d1 (and (not (eq g 1)) (math-poly-div (cdr r1) g)))
  745. X             (d2 (and (not (eq g 1)) (math-poly-div
  746. X                          (math-mul (car r1) (cdr r2))
  747. X                          g))))
  748. X             (if (and (eq (cdr d1) 0) (eq (cdr d2) 0))
  749. X             (cons (list (car expr) (car d2)
  750. X                     (math-mul (car r2) (car d1)))
  751. X                   (math-mul (car d1) (cdr r2)))
  752. X               (cons (list (car expr)
  753. X                   (math-mul (car r1) (cdr r2))
  754. X                   (math-mul (car r2) (cdr r1)))
  755. X                 (math-mul (cdr r1) (cdr r2)))))))))))
  756. X    ((eq (car expr) '*)
  757. X     (let* ((r1 (math-to-ratpoly-rec (nth 1 expr)))
  758. X        (r2 (math-to-ratpoly-rec (nth 2 expr)))
  759. X        (g (math-mul (math-poly-gcd (car r1) (cdr r2))
  760. X                 (math-poly-gcd (cdr r1) (car r2)))))
  761. X       (if (eq g 1)
  762. X           (cons (math-mul (car r1) (car r2))
  763. X             (math-mul (cdr r1) (cdr r2)))
  764. X         (cons (math-poly-div-exact (math-mul (car r1) (car r2)) g)
  765. X           (math-poly-div-exact (math-mul (cdr r1) (cdr r2)) g)))))
  766. X    ((eq (car expr) '/)
  767. X     (let* ((r1 (math-to-ratpoly-rec (nth 1 expr)))
  768. X        (r2 (math-to-ratpoly-rec (nth 2 expr))))
  769. X       (if (and (eq (cdr r1) 1) (eq (cdr r2) 1))
  770. X           (cons (car r1) (car r2))
  771. X         (let ((g (math-mul (math-poly-gcd (car r1) (car r2))
  772. X                (math-poly-gcd (cdr r1) (cdr r2)))))
  773. X           (if (eq g 1)
  774. X           (cons (math-mul (car r1) (cdr r2))
  775. X             (math-mul (cdr r1) (car r2)))
  776. X         (cons (math-poly-div-exact (math-mul (car r1) (cdr r2)) g)
  777. X               (math-poly-div-exact (math-mul (cdr r1) (car r2))
  778. X                        g)))))))
  779. X    ((and (eq (car expr) '^) (integerp (nth 2 expr)))
  780. X     (let ((r1 (math-to-ratpoly-rec (nth 1 expr))))
  781. X       (if (> (nth 2 expr) 0)
  782. X           (cons (math-pow (car r1) (nth 2 expr))
  783. X             (math-pow (cdr r1) (nth 2 expr)))
  784. X         (cons (math-pow (cdr r1) (- (nth 2 expr)))
  785. X           (math-pow (car r1) (- (nth 2 expr)))))))
  786. X    ((eq (car expr) 'neg)
  787. X     (let ((r1 (math-to-ratpoly-rec (nth 1 expr))))
  788. X       (cons (math-neg (car r1)) (cdr r1))))
  789. X    (t (cons expr 1)))
  790. )
  791. X
  792. X
  793. (defun math-ratpoly-p (expr &optional var)
  794. X  (cond ((equal expr var) 1)
  795. X    ((Math-primp expr) 0)
  796. X    ((memq (car expr) '(+ -))
  797. X     (let ((p1 (math-ratpoly-p (nth 1 expr) var))
  798. X           p2)
  799. X       (and p1 (setq p2 (math-ratpoly-p (nth 2 expr) var))
  800. X        (max p1 p2))))
  801. X    ((eq (car expr) '*)
  802. X     (let ((p1 (math-ratpoly-p (nth 1 expr) var))
  803. X           p2)
  804. X       (and p1 (setq p2 (math-ratpoly-p (nth 2 expr) var))
  805. X        (+ p1 p2))))
  806. X    ((eq (car expr) 'neg)
  807. X     (math-ratpoly-p (nth 1 expr) var))
  808. X    ((eq (car expr) '/)
  809. X     (let ((p1 (math-ratpoly-p (nth 1 expr) var))
  810. X           p2)
  811. X       (and p1 (setq p2 (math-ratpoly-p (nth 2 expr) var))
  812. X        (- p1 p2))))
  813. X    ((and (eq (car expr) '^)
  814. X          (integerp (nth 2 expr)))
  815. X     (let ((p1 (math-ratpoly-p (nth 1 expr) var)))
  816. X       (and p1 (* p1 (nth 2 expr)))))
  817. X    ((not var) 1)
  818. X    ((math-poly-depends expr var) nil)
  819. X    (t 0))
  820. )
  821. X
  822. X
  823. (defun calcFunc-apart (expr &optional var)
  824. X  (cond ((Math-primp expr) expr)
  825. X    ((eq (car expr) '+)
  826. X     (math-add (calcFunc-apart (nth 1 expr) var)
  827. X           (calcFunc-apart (nth 2 expr) var)))
  828. X    ((eq (car expr) '-)
  829. X     (math-sub (calcFunc-apart (nth 1 expr) var)
  830. X           (calcFunc-apart (nth 2 expr) var)))
  831. X    ((not (math-ratpoly-p expr var))
  832. X     (math-reject-arg expr "Expected a rational function"))
  833. X    (t
  834. X     (let* ((calc-prefer-frac t)
  835. X        (rat (math-to-ratpoly expr))
  836. X        (num (car rat))
  837. X        (den (cdr rat))
  838. X        (qr (math-poly-div num den))
  839. X        (q (car qr))
  840. X        (r (cdr qr)))
  841. X       (or var
  842. X           (setq var (math-polynomial-base den)))
  843. X       (math-add q (or (and var
  844. X                (math-expr-contains den var)
  845. X                (math-partial-fractions r den var))
  846. X               (math-div r den))))))
  847. )
  848. X
  849. X
  850. (defun math-padded-polynomial (expr var deg)
  851. X  (let ((p (math-is-polynomial expr var deg)))
  852. X    (append p (make-list (- deg (length p)) 0)))
  853. )
  854. X
  855. (defun math-partial-fractions (r den var)
  856. X  (let* ((fden (calcFunc-factors den var))
  857. X     (tdeg (math-polynomial-p den var))
  858. X     (fp fden)
  859. X     (dlist nil)
  860. X     (eqns 0)
  861. X     (lz nil)
  862. X     (tz (make-list (1- tdeg) 0))
  863. X     (calc-matrix-mode 'scalar))
  864. X    (and (not (and (= (length fden) 2) (eq (nth 2 (nth 1 fden)) 1)))
  865. X     (progn
  866. X       (while (setq fp (cdr fp))
  867. X         (let ((rpt (nth 2 (car fp)))
  868. X           (deg (math-polynomial-p (nth 1 (car fp)) var))
  869. X           dnum dvar deg2)
  870. X           (while (> rpt 0)
  871. X         (setq deg2 deg
  872. X               dnum 0)
  873. X         (while (> deg2 0)
  874. X           (setq dvar (append '(vec) lz '(1) tz)
  875. X             lz (cons 0 lz)
  876. X             tz (cdr tz)
  877. X             deg2 (1- deg2)
  878. X             dnum (math-add dnum (math-mul dvar
  879. X                               (math-pow var deg2)))
  880. X             dlist (cons (and (= deg2 (1- deg))
  881. X                      (math-pow (nth 1 (car fp)) rpt))
  882. X                     dlist)))
  883. X         (let ((fpp fden)
  884. X               (mult 1))
  885. X           (while (setq fpp (cdr fpp))
  886. X             (or (eq fpp fp)
  887. X             (setq mult (math-mul mult
  888. X                          (math-pow (nth 1 (car fpp))
  889. X                            (nth 2 (car fpp)))))))
  890. X           (setq dnum (math-mul dnum mult)))
  891. X         (setq eqns (math-add eqns (math-mul dnum
  892. X                             (math-pow
  893. X                              (nth 1 (car fp))
  894. X                              (- (nth 2 (car fp))
  895. X                             rpt))))
  896. X               rpt (1- rpt)))))
  897. X       (setq eqns (math-div (cons 'vec (math-padded-polynomial r var tdeg))
  898. X                (math-transpose
  899. X                 (cons 'vec
  900. X                       (mapcar
  901. X                    (function
  902. X                     (lambda (x)
  903. X                       (cons 'vec (math-padded-polynomial
  904. X                               x var tdeg))))
  905. X                    (cdr eqns))))))
  906. X       (and (math-vectorp eqns)
  907. X        (let ((res 0)
  908. X              (num nil))
  909. X          (setq eqns (nreverse eqns))
  910. X          (while eqns
  911. X            (setq num (cons (car eqns) num)
  912. X              eqns (cdr eqns))
  913. X            (if (car dlist)
  914. X            (setq num (math-build-polynomial-expr
  915. X                   (nreverse num) var)
  916. X                  res (math-add res (math-div num (car dlist)))
  917. X                  num nil))
  918. X            (setq dlist (cdr dlist)))
  919. X          (math-normalize res))))))
  920. )
  921. X
  922. X
  923. X
  924. (defun math-expand-term (expr)
  925. X  (cond ((and (eq (car-safe expr) '*)
  926. X          (memq (car-safe (nth 1 expr)) '(+ -)))
  927. X     (math-add-or-sub (list '* (nth 1 (nth 1 expr)) (nth 2 expr))
  928. X              (list '* (nth 2 (nth 1 expr)) (nth 2 expr))
  929. X              nil (eq (car (nth 1 expr)) '-)))
  930. X    ((and (eq (car-safe expr) '*)
  931. X          (memq (car-safe (nth 2 expr)) '(+ -)))
  932. X     (math-add-or-sub (list '* (nth 1 expr) (nth 1 (nth 2 expr)))
  933. X              (list '* (nth 1 expr) (nth 2 (nth 2 expr)))
  934. X              nil (eq (car (nth 2 expr)) '-)))
  935. X    ((and (eq (car-safe expr) '/)
  936. X          (memq (car-safe (nth 1 expr)) '(+ -)))
  937. X     (math-add-or-sub (list '/ (nth 1 (nth 1 expr)) (nth 2 expr))
  938. X              (list '/ (nth 2 (nth 1 expr)) (nth 2 expr))
  939. X              nil (eq (car (nth 1 expr)) '-)))
  940. X    ((and (eq (car-safe expr) '^)
  941. X          (memq (car-safe (nth 1 expr)) '(+ -))
  942. X          (integerp (nth 2 expr))
  943. X          (if (> (nth 2 expr) 0)
  944. X          (or (and (or (> mmt-many 500000) (< mmt-many -500000))
  945. X               (math-expand-power (nth 1 expr) (nth 2 expr)
  946. X                          nil t))
  947. X              (list '*
  948. X                (nth 1 expr)
  949. X                (list '^ (nth 1 expr) (1- (nth 2 expr)))))
  950. X        (if (< (nth 2 expr) 0)
  951. X            (list '/ 1 (list '^ (nth 1 expr) (- (nth 2 expr))))))))
  952. X    (t expr))
  953. )
  954. X
  955. (defun calcFunc-expand (expr &optional many)
  956. X  (math-normalize (math-map-tree 'math-expand-term expr many))
  957. )
  958. X
  959. (defun math-expand-power (x n &optional var else-nil)
  960. X  (or (and (natnump n)
  961. X       (memq (car-safe x) '(+ -))
  962. X       (let ((terms nil)
  963. X         (cterms nil))
  964. X         (while (memq (car-safe x) '(+ -))
  965. X           (setq terms (cons (if (eq (car x) '-)
  966. X                     (math-neg (nth 2 x))
  967. X                   (nth 2 x))
  968. X                 terms)
  969. X             x (nth 1 x)))
  970. X         (setq terms (cons x terms))
  971. X         (if var
  972. X         (let ((p terms))
  973. X           (while p
  974. X             (or (math-expr-contains (car p) var)
  975. X             (setq terms (delq (car p) terms)
  976. X                   cterms (cons (car p) cterms)))
  977. X             (setq p (cdr p)))
  978. X           (if cterms
  979. X               (setq terms (cons (apply 'calcFunc-add cterms)
  980. X                     terms)))))
  981. X         (if (= (length terms) 2)
  982. X         (let ((i 0)
  983. X               (accum 0))
  984. X           (while (<= i n)
  985. X             (setq accum (list '+ accum
  986. X                       (list '* (calcFunc-choose n i)
  987. X                         (list '*
  988. X                           (list '^ (nth 1 terms) i)
  989. X                           (list '^ (car terms)
  990. X                             (- n i)))))
  991. X               i (1+ i)))
  992. X           accum)
  993. X           (if (= n 2)
  994. X           (let ((accum 0)
  995. X             (p1 terms)
  996. X             p2)
  997. X             (while p1
  998. X               (setq accum (list '+ accum
  999. X                     (list '^ (car p1) 2))
  1000. X                 p2 p1)
  1001. X               (while (setq p2 (cdr p2))
  1002. X             (setq accum (list '+ accum
  1003. X                       (list '* 2 (list '*
  1004. X                                (car p1)
  1005. X                                (car p2))))))
  1006. X               (setq p1 (cdr p1)))
  1007. X             accum)
  1008. X         (if (= n 3)
  1009. X             (let ((accum 0)
  1010. X               (p1 terms)
  1011. X               p2 p3)
  1012. X               (while p1
  1013. X             (setq accum (list '+ accum (list '^ (car p1) 3))
  1014. X                   p2 p1)
  1015. X             (while (setq p2 (cdr p2))
  1016. X               (setq accum (list '+
  1017. X                         (list '+
  1018. X                           accum
  1019. X                           (list '* 3
  1020. X                             (list
  1021. X                              '*
  1022. X                              (list '^ (car p1) 2)
  1023. X                              (car p2))))
  1024. X                         (list '* 3
  1025. X                           (list
  1026. X                            '* (car p1)
  1027. X                            (list '^ (car p2) 2))))
  1028. X                 p3 p2)
  1029. X               (while (setq p3 (cdr p3))
  1030. X                 (setq accum (list '+ accum
  1031. X                           (list '* 6
  1032. X                             (list '*
  1033. X                               (car p1)
  1034. X                               (list
  1035. X                                '* (car p2)
  1036. X                                (car p3))))))))
  1037. X             (setq p1 (cdr p1)))
  1038. X               accum))))))
  1039. X      (and (not else-nil)
  1040. X       (list '^ x n)))
  1041. )
  1042. X
  1043. (defun calcFunc-expandpow (x n)
  1044. X  (math-normalize (math-expand-power x n))
  1045. )
  1046. X
  1047. X
  1048. X
  1049. SHAR_EOF
  1050. echo 'File calc-poly.el is complete' &&
  1051. chmod 0644 calc-poly.el ||
  1052. echo 'restore of calc-poly.el failed'
  1053. Wc_c="`wc -c < 'calc-poly.el'`"
  1054. test 35651 -eq "$Wc_c" ||
  1055.     echo 'calc-poly.el: original size 35651, current size' "$Wc_c"
  1056. rm -f _shar_wnt_.tmp
  1057. fi
  1058. # ============= calc-prog.el ==============
  1059. if test -f 'calc-prog.el' -a X"$1" != X"-c"; then
  1060.     echo 'x - skipping calc-prog.el (File already exists)'
  1061.     rm -f _shar_wnt_.tmp
  1062. else
  1063. > _shar_wnt_.tmp
  1064. echo 'x - extracting calc-prog.el (Text)'
  1065. sed 's/^X//' << 'SHAR_EOF' > 'calc-prog.el' &&
  1066. ;; Calculator for GNU Emacs, part II [calc-prog.el]
  1067. ;; Copyright (C) 1990, 1991 Free Software Foundation, Inc.
  1068. ;; Written by Dave Gillespie, daveg@csvax.cs.caltech.edu.
  1069. X
  1070. ;; This file is part of GNU Emacs.
  1071. X
  1072. ;; GNU Emacs is distributed in the hope that it will be useful,
  1073. ;; but WITHOUT ANY WARRANTY.  No author or distributor
  1074. ;; accepts responsibility to anyone for the consequences of using it
  1075. ;; or for whether it serves any particular purpose or works at all,
  1076. ;; unless he says so in writing.  Refer to the GNU Emacs General Public
  1077. ;; License for full details.
  1078. X
  1079. ;; Everyone is granted permission to copy, modify and redistribute
  1080. ;; GNU Emacs, but only under the conditions described in the
  1081. ;; GNU Emacs General Public License.   A copy of this license is
  1082. ;; supposed to have been given to you along with GNU Emacs so you
  1083. ;; can know your rights and responsibilities.  It should be in a
  1084. ;; file named COPYING.  Among other things, the copyright notice
  1085. ;; and this notice must be preserved on all copies.
  1086. X
  1087. X
  1088. X
  1089. ;; This file is autoloaded from calc-ext.el.
  1090. (require 'calc-ext)
  1091. X
  1092. (require 'calc-macs)
  1093. X
  1094. (defun calc-Need-calc-prog () nil)
  1095. X
  1096. X
  1097. (defun calc-equal-to (arg)
  1098. X  (interactive "P")
  1099. X  (calc-wrapper
  1100. X   (if (and (integerp arg) (> arg 2))
  1101. X       (calc-enter-result arg "eq" (cons 'calcFunc-eq (calc-top-list-n arg)))
  1102. X     (calc-binary-op "eq" 'calcFunc-eq arg)))
  1103. )
  1104. X
  1105. (defun calc-remove-equal (arg)
  1106. X  (interactive "P")
  1107. X  (calc-wrapper
  1108. X   (calc-unary-op "rmeq" 'calcFunc-rmeq arg))
  1109. )
  1110. X
  1111. (defun calc-not-equal-to (arg)
  1112. X  (interactive "P")
  1113. X  (calc-wrapper
  1114. X   (if (and (integerp arg) (> arg 2))
  1115. X       (calc-enter-result arg "neq" (cons 'calcFunc-neq (calc-top-list-n arg)))
  1116. X     (calc-binary-op "neq" 'calcFunc-neq arg)))
  1117. )
  1118. X
  1119. (defun calc-less-than (arg)
  1120. X  (interactive "P")
  1121. X  (calc-wrapper
  1122. X   (calc-binary-op "lt" 'calcFunc-lt arg))
  1123. )
  1124. X
  1125. (defun calc-greater-than (arg)
  1126. X  (interactive "P")
  1127. X  (calc-wrapper
  1128. X   (calc-binary-op "gt" 'calcFunc-gt arg))
  1129. )
  1130. X
  1131. (defun calc-less-equal (arg)
  1132. X  (interactive "P")
  1133. X  (calc-wrapper
  1134. X   (calc-binary-op "leq" 'calcFunc-leq arg))
  1135. )
  1136. X
  1137. (defun calc-greater-equal (arg)
  1138. X  (interactive "P")
  1139. X  (calc-wrapper
  1140. X   (calc-binary-op "geq" 'calcFunc-geq arg))
  1141. )
  1142. X
  1143. (defun calc-in-set (arg)
  1144. X  (interactive "P")
  1145. X  (calc-wrapper
  1146. X   (calc-binary-op "in" 'calcFunc-in arg))
  1147. )
  1148. X
  1149. (defun calc-logical-and (arg)
  1150. X  (interactive "P")
  1151. X  (calc-wrapper
  1152. X   (calc-binary-op "land" 'calcFunc-land arg 1))
  1153. )
  1154. X
  1155. (defun calc-logical-or (arg)
  1156. X  (interactive "P")
  1157. X  (calc-wrapper
  1158. X   (calc-binary-op "lor" 'calcFunc-lor arg 0))
  1159. )
  1160. X
  1161. (defun calc-logical-not (arg)
  1162. X  (interactive "P")
  1163. X  (calc-wrapper
  1164. X   (calc-unary-op "lnot" 'calcFunc-lnot arg))
  1165. )
  1166. X
  1167. (defun calc-logical-if ()
  1168. X  (interactive)
  1169. X  (calc-wrapper
  1170. X   (calc-enter-result 3 "if" (cons 'calcFunc-if (calc-top-list-n 3))))
  1171. )
  1172. X
  1173. X
  1174. X
  1175. X
  1176. X
  1177. (defun calc-timing (n)
  1178. X  (interactive "P")
  1179. X  (calc-wrapper
  1180. X   (calc-change-mode 'calc-timing n nil t)
  1181. X   (message (if calc-timing
  1182. X        "Reporting timing of slow commands in Trail."
  1183. X          "Not reporting timing of commands.")))
  1184. )
  1185. X
  1186. (defun calc-pass-errors ()
  1187. X  (interactive)
  1188. X  ;; The following two cases are for the new, optimizing byte compiler
  1189. X  ;; or the standard 18.57 byte compiler, respectively.
  1190. X  (condition-case err
  1191. X      (let ((place (aref (nth 2 (nth 2 (symbol-function 'calc-do))) 15)))
  1192. X    (or (memq (car-safe (car-safe place)) '(error xxxerror))
  1193. X        (setq place (aref (nth 2 (nth 2 (symbol-function 'calc-do))) 27)))
  1194. X    (or (memq (car (car place)) '(error xxxerror))
  1195. X        (error "foo"))
  1196. X    (setcar (car place) 'xxxerror))
  1197. X    (error (error "The calc-do function has been modified; unable to patch.")))
  1198. )
  1199. X
  1200. (defun calc-user-define ()
  1201. X  (interactive)
  1202. X  (message "Define user key: z-")
  1203. X  (let ((key (read-char)))
  1204. X    (if (= (calc-user-function-classify key) 0)
  1205. X    (error "Can't redefine \"?\" key"))
  1206. X    (let ((func (intern (completing-read (concat "Set key z "
  1207. X                         (char-to-string key)
  1208. X                         " to command: ")
  1209. X                     obarray
  1210. X                     'commandp
  1211. X                     t
  1212. X                     "calc-"))))
  1213. X      (let* ((kmap (calc-user-key-map))
  1214. X         (old (assq key kmap)))
  1215. X    (if old
  1216. X        (setcdr old func)
  1217. X      (setcdr kmap (cons (cons key func) (cdr kmap)))))))
  1218. )
  1219. X
  1220. (defun calc-user-undefine ()
  1221. X  (interactive)
  1222. X  (message "Undefine user key: z-")
  1223. X  (let ((key (read-char)))
  1224. X    (if (= (calc-user-function-classify key) 0)
  1225. X    (error "Can't undefine \"?\" key"))
  1226. X    (let* ((kmap (calc-user-key-map)))
  1227. X      (delq (or (assq key kmap)
  1228. X        (assq (upcase key) kmap)
  1229. X        (assq (downcase key) kmap)
  1230. X        (error "No such user key is defined"))
  1231. X        kmap)))
  1232. )
  1233. X
  1234. (defun calc-user-define-formula ()
  1235. X  (interactive)
  1236. X  (calc-wrapper
  1237. X   (let* ((form (calc-top 1))
  1238. X      (arglist nil)
  1239. X      (is-lambda (and (eq (car-safe form) 'calcFunc-lambda)
  1240. X              (>= (length form) 2)))
  1241. X      odef key keyname cmd cmd-base func alist is-symb)
  1242. X     (if is-lambda
  1243. X     (setq arglist (mapcar (function (lambda (x) (nth 1 x)))
  1244. X                   (nreverse (cdr (reverse (cdr form)))))
  1245. X           form (nth (1- (length form)) form))
  1246. X       (calc-default-formula-arglist form)
  1247. X       (setq arglist (sort arglist 'string-lessp)))
  1248. X     (message "Define user key: z-")
  1249. X     (setq key (read-char))
  1250. X     (if (= (calc-user-function-classify key) 0)
  1251. X     (error "Can't redefine \"?\" key"))
  1252. X     (setq key (and (not (memq key '(13 32))) key)
  1253. X       keyname (and key
  1254. X            (if (or (and (<= ?0 key) (<= key ?9))
  1255. X                (and (<= ?a key) (<= key ?z))
  1256. X                (and (<= ?A key) (<= key ?Z)))
  1257. X                (char-to-string key)
  1258. X              (format "%03d" key)))
  1259. X       odef (assq key (calc-user-key-map)))
  1260. X     (while
  1261. X     (progn
  1262. X       (setq cmd (completing-read "Define M-x command name: "
  1263. X                      obarray 'commandp nil
  1264. X                      (if (and odef (symbolp (cdr odef)))
  1265. X                      (symbol-name (cdr odef))
  1266. X                    "calc-"))
  1267. X         cmd-base (and (string-match "\\`calc-\\(.+\\)\\'" cmd)
  1268. X                   (math-match-substring cmd 1))
  1269. X         cmd (and (not (or (string-equal cmd "")
  1270. X                   (string-equal cmd "calc-")))
  1271. X              (intern cmd)))
  1272. X       (and cmd
  1273. X        (fboundp cmd)
  1274. X        odef
  1275. X        (not
  1276. X         (y-or-n-p
  1277. X          (if (get cmd 'calc-user-defn)
  1278. X              (concat "Replace previous definition for "
  1279. X                  (symbol-name cmd) "? ")
  1280. X            "That name conflicts with a built-in Emacs function.  Replace this function? "))))))
  1281. X     (if (and key (not cmd))
  1282. X     (setq cmd (intern (concat "calc-User-" keyname))))
  1283. X     (while
  1284. X     (progn
  1285. X       (setq func (completing-read "Define algebraic function name: "
  1286. X                       obarray 'fboundp nil
  1287. X                       (concat "calcFunc-"
  1288. X                           (if cmd-base
  1289. X                           (if (string-match
  1290. X                            "\\`User-.+" cmd-base)
  1291. X                               (concat
  1292. X                            "User"
  1293. X                            (substring cmd-base 5))
  1294. X                             cmd-base)
  1295. X                         "")))
  1296. X         func (and (not (or (string-equal func "")
  1297. X                    (string-equal func "calcFunc-")))
  1298. X               (intern func)))
  1299. X       (and func
  1300. X        (fboundp func)
  1301. X        (not (fboundp cmd))
  1302. X        odef
  1303. X        (not
  1304. X         (y-or-n-p
  1305. X          (if (get func 'calc-user-defn)
  1306. X              (concat "Replace previous definition for "
  1307. X                  (symbol-name func) "? ")
  1308. X            "That name conflicts with a built-in Emacs function.  Replace this function? "))))))
  1309. X     (if (not func)
  1310. X     (setq func (intern (concat "calcFunc-User"
  1311. X                    (or keyname
  1312. X                    (and cmd (symbol-name cmd))
  1313. X                    (format "%05d" (% (random) 10000)))))))
  1314. X     (if is-lambda
  1315. X     (setq alist arglist)
  1316. X       (while
  1317. X       (progn
  1318. X         (setq alist (read-from-minibuffer "Function argument list: "
  1319. X                           (if arglist
  1320. X                           (prin1-to-string arglist)
  1321. X                         "()")
  1322. X                           minibuffer-local-map
  1323. X                           t))
  1324. X         (and (not (calc-subsetp alist arglist))
  1325. X          (not (y-or-n-p
  1326. X            "Okay for arguments that don't appear in formula to be ignored? "))))))
  1327. X     (setq is-symb (and alist
  1328. X            func
  1329. X            (y-or-n-p
  1330. X             "Leave it symbolic for non-constant arguments? ")))
  1331. X     (setq alist (mapcar (function (lambda (x)
  1332. X                     (or (cdr (assq x '((nil . arg-nil)
  1333. X                            (t . arg-t))))
  1334. X                     x))) alist))
  1335. X     (if cmd
  1336. X     (progn
  1337. X       (calc-need-macros)
  1338. X       (fset cmd
  1339. X         (list 'lambda
  1340. X               '()
  1341. X               '(interactive)
  1342. X               (list 'calc-wrapper
  1343. X                 (list 'calc-enter-result
  1344. X                   (length alist)
  1345. X                   (let ((name (symbol-name (or func cmd))))
  1346. X                     (and (string-match
  1347. X                       "\\([^-][^-]?[^-]?[^-]?\\)[^-]*\\'"
  1348. X                       name)
  1349. X                      (math-match-substring name 1)))
  1350. X                   (list 'cons
  1351. X                     (list 'quote func)
  1352. X                     (list 'calc-top-list-n
  1353. X                           (length alist)))))))
  1354. X       (put cmd 'calc-user-defn t)))
  1355. X     (let ((body (list 'math-normalize (calc-fix-user-formula form))))
  1356. X       (fset func
  1357. X         (append
  1358. X          (list 'lambda alist)
  1359. X          (and is-symb
  1360. X           (mapcar (function (lambda (v)
  1361. X                       (list 'math-check-const v t)))
  1362. X               alist))
  1363. X          (list body))))
  1364. X     (put func 'calc-user-defn form)
  1365. X     (setq math-integral-cache-state nil)
  1366. X     (if key
  1367. X     (let* ((kmap (calc-user-key-map))
  1368. X        (old (assq key kmap)))
  1369. X       (if old
  1370. X           (setcdr old cmd)
  1371. X         (setcdr kmap (cons (cons key cmd) (cdr kmap)))))))
  1372. X   (message ""))
  1373. )
  1374. X
  1375. (defun calc-default-formula-arglist (form)
  1376. X  (if (consp form)
  1377. X      (if (eq (car form) 'var)
  1378. X      (if (or (memq (nth 1 form) arglist)
  1379. X          (math-const-var form))
  1380. X          ()
  1381. X        (setq arglist (cons (nth 1 form) arglist)))
  1382. X    (calc-default-formula-arglist-step (cdr form))))
  1383. )
  1384. X
  1385. (defun calc-default-formula-arglist-step (l)
  1386. X  (and l
  1387. X       (progn
  1388. X     (calc-default-formula-arglist (car l))
  1389. X     (calc-default-formula-arglist-step (cdr l))))
  1390. )
  1391. X
  1392. (defun calc-subsetp (a b)
  1393. X  (or (null a)
  1394. X      (and (memq (car a) b)
  1395. X       (calc-subsetp (cdr a) b)))
  1396. )
  1397. X
  1398. (defun calc-fix-user-formula (f)
  1399. X  (if (consp f)
  1400. X      (let (temp)
  1401. X    (cond ((and (eq (car f) 'var)
  1402. X            (memq (setq temp (or (cdr (assq (nth 1 f) '((nil . arg-nil)
  1403. X                                (t . arg-t))))
  1404. X                     (nth 1 f)))
  1405. X              alist))
  1406. X           temp)
  1407. X          ((or (math-constp f) (eq (car f) 'var))
  1408. X           (list 'quote f))
  1409. X          ((and (eq (car f) 'calcFunc-eval)
  1410. X            (= (length f) 2))
  1411. X           (list 'let '((calc-simplify-mode nil))
  1412. X             (list 'math-normalize (calc-fix-user-formula (nth 1 f)))))
  1413. X          ((and (eq (car f) 'calcFunc-evalsimp)
  1414. X            (= (length f) 2))
  1415. X           (list 'math-simplify (calc-fix-user-formula (nth 1 f))))
  1416. X          ((and (eq (car f) 'calcFunc-evalextsimp)
  1417. X            (= (length f) 2))
  1418. X           (list 'math-simplify-extended
  1419. X             (calc-fix-user-formula (nth 1 f))))
  1420. X          (t
  1421. X           (cons 'list
  1422. X             (cons (list 'quote (car f))
  1423. X               (mapcar 'calc-fix-user-formula (cdr f)))))))
  1424. X    f)
  1425. )
  1426. X
  1427. (defun calc-user-define-composition ()
  1428. X  (interactive)
  1429. X  (calc-wrapper
  1430. X   (if (eq calc-language 'unform)
  1431. X       (error "Can't define formats for unformatted mode"))
  1432. X   (let* ((comp (calc-top 1))
  1433. X      (func (intern (completing-read "Define format for which function: "
  1434. X                     obarray 'fboundp nil "calcFunc-")))
  1435. X      (comps (get func 'math-compose-forms))
  1436. X      entry entry2
  1437. X      (arglist nil)
  1438. X      (alist nil))
  1439. X     (if (math-zerop comp)
  1440. X     (if (setq entry (assq calc-language comps))
  1441. X         (put func 'math-compose-forms (delq entry comps)))
  1442. X       (calc-default-formula-arglist comp)
  1443. X       (setq arglist (sort arglist 'string-lessp))
  1444. X       (while
  1445. X       (progn
  1446. X         (setq alist (read-from-minibuffer "Composition argument list: "
  1447. X                           (if arglist
  1448. X                           (prin1-to-string arglist)
  1449. X                         "()")
  1450. X                           minibuffer-local-map
  1451. X                           t))
  1452. X         (and (not (calc-subsetp alist arglist))
  1453. X          (y-or-n-p
  1454. X           "Okay for arguments that don't appear in formula to be invisible? "))))
  1455. X       (or (setq entry (assq calc-language comps))
  1456. X       (put func 'math-compose-forms
  1457. X        (cons (setq entry (list calc-language)) comps)))
  1458. X       (or (setq entry2 (assq (length alist) (cdr entry)))
  1459. X       (setcdr entry
  1460. X           (cons (setq entry2 (list (length alist))) (cdr entry))))
  1461. X       (setcdr entry2 (list 'lambda alist (calc-fix-user-formula comp))))
  1462. X     (calc-pop-stack 1)
  1463. X     (calc-do-refresh)))
  1464. )
  1465. X
  1466. X
  1467. (defun calc-user-define-kbd-macro (arg)
  1468. X  (interactive "P")
  1469. X  (or last-kbd-macro
  1470. X      (error "No keyboard macro defined"))
  1471. X  (message "Define last kbd macro on user key: z-")
  1472. X  (let ((key (read-char)))
  1473. X    (if (= (calc-user-function-classify key) 0)
  1474. X    (error "Can't redefine \"?\" key"))
  1475. X    (let ((cmd (intern (completing-read "Full name for new command: "
  1476. X                    obarray
  1477. X                    'commandp
  1478. X                    nil
  1479. X                    (concat "calc-User-"
  1480. X                        (if (or (and (>= key ?a)
  1481. X                                 (<= key ?z))
  1482. X                            (and (>= key ?A)
  1483. X                                 (<= key ?Z))
  1484. X                            (and (>= key ?0)
  1485. X                                 (<= key ?9)))
  1486. X                            (char-to-string key)
  1487. X                          (format "%03d" key)))))))
  1488. X      (and (fboundp cmd)
  1489. X       (not (let ((f (symbol-function cmd)))
  1490. X          (or (stringp f)
  1491. X              (and (consp f)
  1492. X               (eq (car-safe (nth 3 f))
  1493. X                   'calc-execute-kbd-macro)))))
  1494. X       (error "Function %s is already defined and not a keyboard macro"
  1495. X          cmd))
  1496. X      (put cmd 'calc-user-defn t)
  1497. X      (fset cmd (if (< (prefix-numeric-value arg) 0)
  1498. X            last-kbd-macro
  1499. X          (list 'lambda
  1500. X            '(arg)
  1501. X            '(interactive "P")
  1502. X            (list 'calc-execute-kbd-macro
  1503. X                  (vector (key-description last-kbd-macro)
  1504. X                      last-kbd-macro)
  1505. X                  'arg
  1506. X                  (format "z%c" key)))))
  1507. X      (let* ((kmap (calc-user-key-map))
  1508. X         (old (assq key kmap)))
  1509. X    (if old
  1510. X        (setcdr old cmd)
  1511. X      (setcdr kmap (cons (cons key cmd) (cdr kmap)))))))
  1512. )
  1513. X
  1514. X
  1515. (defun calc-user-define-invocation ()
  1516. X  (interactive)
  1517. X  (or last-kbd-macro
  1518. X      (error "No keyboard macro defined"))
  1519. X  (setq calc-invocation-macro last-kbd-macro)
  1520. X  (message "Use `M-# Z' to invoke this macro")
  1521. )
  1522. X
  1523. X
  1524. (defun calc-user-define-edit (prefix)
  1525. X  (interactive "P")  ; but no calc-wrapper!
  1526. X  (message "Edit definition of command: z-")
  1527. X  (let* ((key (read-char))
  1528. X     (def (or (assq key (calc-user-key-map))
  1529. X          (assq (upcase key) (calc-user-key-map))
  1530. X          (assq (downcase key) (calc-user-key-map))
  1531. X          (error "No command defined for that key")))
  1532. X     (cmd (cdr def)))
  1533. X    (if (symbolp cmd)
  1534. X    (setq cmd (symbol-function cmd)))
  1535. X    (cond ((or (stringp cmd)
  1536. X           (and (consp cmd)
  1537. X            (eq (car-safe (nth 3 cmd)) 'calc-execute-kbd-macro)))
  1538. X       (if (and (>= (prefix-numeric-value prefix) 0)
  1539. X            (fboundp 'edit-kbd-macro)
  1540. X            (symbolp (cdr def))
  1541. X            (eq major-mode 'calc-mode))
  1542. X           (progn
  1543. X         (if (and (< (window-width) (screen-width))
  1544. X              calc-display-trail)
  1545. X             (let ((win (get-buffer-window (calc-trail-buffer))))
  1546. X               (if win
  1547. X               (delete-window win))))
  1548. X         (edit-kbd-macro (cdr def) prefix nil
  1549. X                 (function
  1550. X                  (lambda (x)
  1551. X                    (and calc-display-trail
  1552. X                     (calc-wrapper
  1553. X                      (calc-trail-display 1 t)))))
  1554. X                 (function
  1555. X                  (lambda (cmd)
  1556. X                    (if (stringp (symbol-function cmd))
  1557. X                    (symbol-function cmd)
  1558. X                      (let ((mac (nth 1 (nth 3 (symbol-function
  1559. X                                cmd)))))
  1560. X                    (if (vectorp mac)
  1561. X                        (aref mac 1)
  1562. X                      mac)))))
  1563. X                 (function
  1564. X                  (lambda (new cmd)
  1565. X                    (if (stringp (symbol-function cmd))
  1566. X                    (fset cmd new)
  1567. X                      (let ((mac (cdr (nth 3 (symbol-function
  1568. X                                  cmd)))))
  1569. X                    (if (vectorp (car mac))
  1570. X                        (progn
  1571. X                          (aset (car mac) 0
  1572. X                            (key-description new))
  1573. X                          (aset (car mac) 1 new))
  1574. X                      (setcar mac new))))))))
  1575. X         (let ((keys (progn (and (fboundp 'edit-kbd-macro)
  1576. X                     (edit-kbd-macro nil))
  1577. X                (fboundp 'MacEdit-parse-keys))))
  1578. X           (calc-wrapper
  1579. X        (calc-edit-mode (list 'calc-finish-macro-edit
  1580. X                      (list 'quote def)
  1581. X                      keys)
  1582. X                t)
  1583. X        (if keys
  1584. X            (let (top
  1585. X              (fill-column 70)
  1586. X              (fill-prefix nil))
  1587. X              (insert "Notations: RET, SPC, TAB, DEL, LFD, NUL"
  1588. X                  ", C-xxx, M-xxx.\n\n")
  1589. X              (setq top (point))
  1590. X              (insert (if (stringp cmd)
  1591. X                  (key-description cmd)
  1592. X                (if (vectorp (nth 1 (nth 3 cmd)))
  1593. X                    (aref (nth 1 (nth 3 cmd)) 0)
  1594. X                  (key-description (nth 1 (nth 3 cmd)))))
  1595. X                  "\n")
  1596. X              (if (>= (prog2 (forward-char -1)
  1597. X                     (current-column)
  1598. X                     (forward-char 1))
  1599. X                  (screen-width))
  1600. X              (fill-region top (point))))
  1601. X          (insert "Press C-q to quote control characters like RET"
  1602. X              " and TAB.\n"
  1603. X              (if (stringp cmd)
  1604. X                  cmd
  1605. X                (if (vectorp (nth 1 (nth 3 cmd)))
  1606. X                (aref (nth 1 (nth 3 cmd)) 1)
  1607. X                  (nth 1 (nth 3 cmd)))))))
  1608. X           (calc-show-edit-buffer)
  1609. X           (forward-line (if keys 2 1)))))
  1610. X      (t (let* ((func (calc-stack-command-p cmd))
  1611. X            (defn (and func
  1612. X                   (symbolp func)
  1613. X                   (get func 'calc-user-defn))))
  1614. X           (if (and defn (calc-valid-formula-func func))
  1615. X           (progn
  1616. X             (calc-wrapper
  1617. X              (calc-edit-mode (list 'calc-finish-formula-edit
  1618. X                        (list 'quote func)))
  1619. X              (insert (math-showing-full-precision
  1620. X                   (math-format-nice-expr defn (screen-width)))
  1621. X                  "\n"))
  1622. X             (calc-show-edit-buffer))
  1623. X         (error "That command's definition cannot be edited"))))))
  1624. )
  1625. X
  1626. (defun calc-finish-macro-edit (def keys)
  1627. X  (forward-line 1)
  1628. X  (if (and keys (looking-at "\n")) (forward-line 1))
  1629. X  (let* ((true-str (buffer-substring (point) (point-max)))
  1630. X     (str true-str))
  1631. X    (if keys (setq str (MacEdit-parse-keys str)))
  1632. X    (if (symbolp (cdr def))
  1633. X    (if (stringp (symbol-function (cdr def)))
  1634. X        (fset (cdr def) str)
  1635. X      (let ((mac (cdr (nth 3 (symbol-function (cdr def))))))
  1636. X        (if (vectorp (car mac))
  1637. X        (progn
  1638. X          (aset (car mac) 0 (if keys true-str (key-description str)))
  1639. X          (aset (car mac) 1 str))
  1640. X          (setcar mac str))))
  1641. X      (setcdr def str)))
  1642. )
  1643. X
  1644. ;;; The following are hooks into the MacEdit package from macedit.el.
  1645. (put 'calc-execute-extended-command 'MacEdit-print
  1646. X     (function (lambda ()
  1647. X         (setq macro-str (concat "\excalc-" macro-str))))
  1648. )
  1649. X
  1650. (put 'calcDigit-start 'MacEdit-print
  1651. X     (function (lambda ()
  1652. X         (if calc-algebraic-mode
  1653. X             (calc-macro-edit-algebraic)
  1654. X           (MacEdit-unread-chars key-last)
  1655. X           (let ((str "")
  1656. X             (min-bsp 0)
  1657. X             ch last)
  1658. X             (while (and (setq ch (MacEdit-read-char))
  1659. X                 (or (and (>= ch ?0) (<= ch ?9))
  1660. X                     (memq ch '(?\. ?e ?\_ ?n ?\: ?\# ?M
  1661. X                            ?o ?h ?\@ ?\"))
  1662. X                     (and (memq ch '(?\' ?m ?s))
  1663. X                      (string-match "[@oh]" str))
  1664. X                     (and (or (and (>= ch ?a) (<= ch ?z))
  1665. X                          (and (>= ch ?A) (<= ch ?Z)))
  1666. X                      (string-match
  1667. X                       "^[-+]?\\(1[1-9]\\|[2-9][0-9]\\)#"
  1668. X                       str))
  1669. X                     (and (memq ch '(?\177 ?\C-h))
  1670. X                      (> (length str) 0))
  1671. X                     (and (memq ch '(?+ ?-))
  1672. X                      (> (length str) 0)
  1673. X                      (eq (aref str (1- (length str)))
  1674. X                          ?e))))
  1675. X               (if (or (and (>= ch ?0) (<= ch ?9))
  1676. X                   (and (or (not (memq ch '(?\177 ?\C-h)))
  1677. X                    (<= (length str) min-bsp))
  1678. X                    (setq min-bsp (1+ (length str)))))
  1679. X               (setq str (concat str (char-to-string ch)))
  1680. X             (setq str (substring str 0 -1))))
  1681. X             (if (memq ch '(32 10 13))
  1682. X             (setq str (concat str (char-to-string ch)))
  1683. X               (MacEdit-unread-chars ch))
  1684. X             (insert "type \"")
  1685. X             (MacEdit-insert-string str)
  1686. X             (insert "\"\n")))))
  1687. )
  1688. X
  1689. (defun calc-macro-edit-algebraic ()
  1690. X  (MacEdit-unread-chars key-last)
  1691. X  (let ((str "")
  1692. X    (min-bsp 0))
  1693. X    (while (progn
  1694. X         (MacEdit-lookup-key calc-alg-ent-map)
  1695. X         (or (and (memq key-symbol '(self-insert-command
  1696. X                     calcAlg-previous))
  1697. X              (< (length str) 60))
  1698. X         (memq key-symbol
  1699. X                '(backward-delete-char
  1700. X                  delete-backward-char
  1701. X                  backward-delete-char-untabify))
  1702. X         (eq key-last 9)))
  1703. X      (setq macro-str (substring macro-str (length key-str)))
  1704. X      (if (or (eq key-symbol 'self-insert-command)
  1705. X          (and (or (not (memq key-symbol '(backward-delete-char
  1706. X                           delete-backward-char
  1707. X                           backward-delete-char-untabify)))
  1708. X               (<= (length str) min-bsp))
  1709. X           (setq min-bsp (+ (length str) (length key-str)))))
  1710. X      (setq str (concat str key-str))
  1711. X    (setq str (substring str 0 -1))))
  1712. X    (if (memq key-last '(10 13))
  1713. X    (setq str (concat str key-str)
  1714. X          macro-str (substring macro-str (length key-str))))
  1715. X    (if (> (length str) 0)
  1716. X    (progn
  1717. X      (insert "type \"")
  1718. X      (MacEdit-insert-string str)
  1719. X      (insert "\"\n"))))
  1720. )
  1721. (put 'calc-algebraic-entry 'MacEdit-print 'calc-macro-edit-algebraic)
  1722. (put 'calc-auto-algebraic-entry 'MacEdit-print 'calc-macro-edit-algebraic)
  1723. X
  1724. (defun calc-macro-edit-variable (&optional no-cmd)
  1725. X  (let ((str "") ch)
  1726. X    (or no-cmd (insert (symbol-name key-symbol) "\n"))
  1727. X    (if (memq (MacEdit-peek-char) '(?\+ ?\- ?\* ?\/ ?\^ ?\|))
  1728. X    (setq str (char-to-string (MacEdit-read-char))))
  1729. X    (if (and (setq ch (MacEdit-peek-char))
  1730. X         (>= ch ?0) (<= ch ?9))
  1731. X    (insert "type \"" str
  1732. X        (char-to-string (MacEdit-read-char)) "\"\n")
  1733. X      (if (> (length str) 0)
  1734. X      (insert "type \"" str "\"\n"))
  1735. X      (MacEdit-read-argument)))
  1736. )
  1737. (put 'calc-store 'MacEdit-print 'calc-macro-edit-variable)
  1738. (put 'calc-store-into 'MacEdit-print 'calc-macro-edit-variable)
  1739. (put 'calc-store-neg 'MacEdit-print 'calc-macro-edit-variable)
  1740. (put 'calc-store-plus 'MacEdit-print 'calc-macro-edit-variable)
  1741. (put 'calc-store-minus 'MacEdit-print 'calc-macro-edit-variable)
  1742. (put 'calc-store-times 'MacEdit-print 'calc-macro-edit-variable)
  1743. (put 'calc-store-div 'MacEdit-print 'calc-macro-edit-variable)
  1744. (put 'calc-store-power 'MacEdit-print 'calc-macro-edit-variable)
  1745. (put 'calc-store-concat 'MacEdit-print 'calc-macro-edit-variable)
  1746. (put 'calc-store-inv 'MacEdit-print 'calc-macro-edit-variable)
  1747. (put 'calc-store-decr 'MacEdit-print 'calc-macro-edit-variable)
  1748. (put 'calc-store-incr 'MacEdit-print 'calc-macro-edit-variable)
  1749. (put 'calc-store-exchange 'MacEdit-print 'calc-macro-edit-variable)
  1750. (put 'calc-unstore 'MacEdit-print 'calc-macro-edit-variable)
  1751. (put 'calc-recall 'MacEdit-print 'calc-macro-edit-variable)
  1752. (put 'calc-let 'MacEdit-print 'calc-macro-edit-variable)
  1753. (put 'calc-permanent-variable 'MacEdit-print 'calc-macro-edit-variable)
  1754. X
  1755. (defun calc-macro-edit-variable-2 ()
  1756. X  (calc-macro-edit-variable)
  1757. X  (calc-macro-edit-variable t)
  1758. )
  1759. (put 'calc-copy-variable 'MacEdit-print 'calc-macro-edit-variable-2)
  1760. (put 'calc-declare-variable 'MacEdit-print 'calc-macro-edit-variable-2)
  1761. X
  1762. (defun calc-macro-edit-quick-digit ()
  1763. X  (insert "type \"" key-str "\"  # " (symbol-name key-symbol) "\n")
  1764. )
  1765. (put 'calc-store-quick 'MacEdit-print 'calc-macro-edit-quick-digit)
  1766. (put 'calc-store-into-quick 'MacEdit-print 'calc-macro-edit-quick-digit)
  1767. (put 'calc-recall-quick 'MacEdit-print 'calc-macro-edit-quick-digit)
  1768. (put 'calc-select-part 'MacEdit-print 'calc-macro-edit-quick-digit)
  1769. (put 'calc-clean-num 'MacEdit-print 'calc-macro-edit-quick-digit)
  1770. X
  1771. X
  1772. (defun calc-finish-formula-edit (func)
  1773. X  (let ((buf (current-buffer))
  1774. X    (str (buffer-substring (point) (point-max)))
  1775. X    (start (point))
  1776. X    (body (calc-valid-formula-func func)))
  1777. X    (set-buffer calc-original-buffer)
  1778. X    (let ((val (math-read-expr str)))
  1779. X      (if (eq (car-safe val) 'error)
  1780. X      (progn
  1781. X        (set-buffer buf)
  1782. X        (goto-char (+ start (nth 1 val)))
  1783. X        (error (nth 2 val))))
  1784. X      (setcar (cdr body)
  1785. X          (let ((alist (nth 1 (symbol-function func))))
  1786. X        (calc-fix-user-formula val)))
  1787. X      (put func 'calc-user-defn val)))
  1788. )
  1789. X
  1790. (defun calc-valid-formula-func (func)
  1791. X  (let ((def (symbol-function func)))
  1792. X    (and (consp def)
  1793. X     (eq (car def) 'lambda)
  1794. X     (progn
  1795. X       (setq def (cdr (cdr def)))
  1796. X       (while (and def
  1797. X               (not (eq (car (car def)) 'math-normalize)))
  1798. X         (setq def (cdr def)))
  1799. X       (car def))))
  1800. )
  1801. X
  1802. X
  1803. (defun calc-get-user-defn ()
  1804. X  (interactive)
  1805. X  (calc-wrapper
  1806. X   (message "Get definition of command: z-")
  1807. X   (let* ((key (read-char))
  1808. X      (def (or (assq key (calc-user-key-map))
  1809. X           (assq (upcase key) (calc-user-key-map))
  1810. SHAR_EOF
  1811. true || echo 'restore of calc-prog.el failed'
  1812. fi
  1813. echo 'End of  part 23'
  1814. echo 'File calc-prog.el is continued in part 24'
  1815. echo 24 > _shar_seq_.tmp
  1816. exit 0
  1817. exit 0 # Just in case...
  1818. -- 
  1819. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1820. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1821. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1822. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1823.