root/trunk/lisp/calc/calc-alg.el

Revision 4220, 68.6 kB (checked in by miyoshi, 9 months ago)

Sync up with Emacs22.2.

Line 
1 ;;; calc-alg.el --- algebraic functions for Calc
2
3 ;; Copyright (C) 1990, 1991, 1992, 1993, 2001, 2002, 2003, 2004,
4 ;;   2005, 2006, 2007, 2008 Free Software Foundation, Inc.
5
6 ;; Author: David Gillespie <daveg@synaptics.com>
7 ;; Maintainer: Jay Belanger  <jay.p.belanger@gmail.com>
8
9 ;; This file is part of GNU Emacs.
10
11 ;; GNU Emacs is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 3, or (at your option)
14 ;; any later version.
15
16 ;; GNU Emacs is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 ;; GNU General Public License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
23 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 ;; Boston, MA 02110-1301, USA.
25
26 ;;; Commentary:
27
28 ;;; Code:
29
30 ;; This file is autoloaded from calc-ext.el.
31
32 (require 'calc-ext)
33 (require 'calc-macs)
34
35 ;;; Algebra commands.
36
37 (defun calc-alg-evaluate (arg)
38   (interactive "p")
39   (calc-slow-wrapper
40    (calc-with-default-simplification
41     (let ((math-simplify-only nil))
42       (calc-modify-simplify-mode arg)
43       (calc-enter-result 1 "dsmp" (calc-top 1))))))
44
45 (defun calc-modify-simplify-mode (arg)
46   (if (= (math-abs arg) 2)
47       (setq calc-simplify-mode 'alg)
48     (if (>= (math-abs arg) 3)
49         (setq calc-simplify-mode 'ext)))
50   (if (< arg 0)
51       (setq calc-simplify-mode (list calc-simplify-mode))))
52
53 (defun calc-simplify ()
54   (interactive)
55   (calc-slow-wrapper
56    (calc-with-default-simplification
57     (calc-enter-result 1 "simp" (math-simplify (calc-top-n 1))))))
58
59 (defun calc-simplify-extended ()
60   (interactive)
61   (calc-slow-wrapper
62    (calc-with-default-simplification
63     (calc-enter-result 1 "esmp" (math-simplify-extended (calc-top-n 1))))))
64
65 (defun calc-expand-formula (arg)
66   (interactive "p")
67   (calc-slow-wrapper
68    (calc-with-default-simplification
69     (let ((math-simplify-only nil))
70       (calc-modify-simplify-mode arg)
71       (calc-enter-result 1 "expf"
72                          (if (> arg 0)
73                              (let ((math-expand-formulas t))
74                                (calc-top-n 1))
75                            (let ((top (calc-top-n 1)))
76                              (or (math-expand-formula top)
77                                  top))))))))
78
79 (defun calc-factor (arg)
80   (interactive "P")
81   (calc-slow-wrapper
82    (calc-unary-op "fctr" (if (calc-is-hyperbolic)
83                              'calcFunc-factors 'calcFunc-factor)
84                   arg)))
85
86 (defun calc-expand (n)
87   (interactive "P")
88   (calc-slow-wrapper
89    (calc-enter-result 1 "expa"
90                       (append (list 'calcFunc-expand
91                                     (calc-top-n 1))
92                               (and n (list (prefix-numeric-value n)))))))
93
94 ;;; Write out powers (a*b*...)^n as a*b*...*a*b*...
95 (defun calcFunc-powerexpand (expr)
96   (math-normalize (math-map-tree 'math-powerexpand expr)))
97
98 (defun math-powerexpand (expr)
99   (if (eq (car-safe expr) '^)
100       (let ((n (nth 2 expr)))
101         (cond ((and (integerp n)
102                     (> n 0))
103                (let ((i 1)
104                      (a (nth 1 expr))
105                      (prod (nth 1 expr)))
106                  (while (< i n)
107                    (setq prod (math-mul prod a))
108                    (setq i (1+ i)))
109                  prod))
110               ((and (integerp n)
111                     (< n 0))
112                (let ((i -1)
113                      (a (math-pow (nth 1 expr) -1))
114                      (prod (math-pow (nth 1 expr) -1)))
115                  (while (> i n)
116                    (setq prod (math-mul a prod))
117                    (setq i (1- i)))
118                  prod))
119               (t
120                expr)))
121     expr))
122
123 (defun calc-powerexpand ()
124   (interactive)
125   (calc-slow-wrapper
126    (calc-enter-result 1 "pexp"
127                       (calcFunc-powerexpand (calc-top-n 1)))))
128
129 (defun calc-collect (&optional var)
130   (interactive "sCollect terms involving: ")
131   (calc-slow-wrapper
132    (if (or (equal var "") (equal var "$") (null var))
133        (calc-enter-result 2 "clct" (cons 'calcFunc-collect
134                                          (calc-top-list-n 2)))
135      (let ((var (math-read-expr var)))
136        (if (eq (car-safe var) 'error)
137            (error "Bad format in expression: %s" (nth 1 var)))
138        (calc-enter-result 1 "clct" (list 'calcFunc-collect
139                                          (calc-top-n 1)
140                                          var))))))
141
142 (defun calc-apart (arg)
143   (interactive "P")
144   (calc-slow-wrapper
145    (calc-unary-op "aprt" 'calcFunc-apart arg)))
146
147 (defun calc-normalize-rat (arg)
148   (interactive "P")
149   (calc-slow-wrapper
150    (calc-unary-op "nrat" 'calcFunc-nrat arg)))
151
152 (defun calc-poly-gcd (arg)
153   (interactive "P")
154   (calc-slow-wrapper
155    (calc-binary-op "pgcd" 'calcFunc-pgcd arg)))
156
157
158 (defun calc-poly-div (arg)
159   (interactive "P")
160   (calc-slow-wrapper
161    (let ((calc-poly-div-remainder nil))
162      (calc-binary-op "pdiv" 'calcFunc-pdiv arg)
163      (if (and calc-poly-div-remainder (null arg))
164          (progn
165            (calc-clear-command-flag 'clear-message)
166            (calc-record calc-poly-div-remainder "prem")
167            (if (not (Math-zerop calc-poly-div-remainder))
168                (message "(Remainder was %s)"
169                         (math-format-flat-expr calc-poly-div-remainder 0))
170              (message "(No remainder)")))))))
171
172 (defun calc-poly-rem (arg)
173   (interactive "P")
174   (calc-slow-wrapper
175    (calc-binary-op "prem" 'calcFunc-prem arg)))
176
177 (defun calc-poly-div-rem (arg)
178   (interactive "P")
179   (calc-slow-wrapper
180    (if (calc-is-hyperbolic)
181        (calc-binary-op "pdvr" 'calcFunc-pdivide arg)
182      (calc-binary-op "pdvr" 'calcFunc-pdivrem arg))))
183
184 (defun calc-substitute (&optional oldname newname)
185   (interactive "sSubstitute old: ")
186   (calc-slow-wrapper
187    (let (old new (num 1) expr)
188      (if (or (equal oldname "") (equal oldname "$") (null oldname))
189          (setq new (calc-top-n 1)
190                old (calc-top-n 2)
191                expr (calc-top-n 3)
192                num 3)
193        (or newname
194            (progn (calc-unread-command ?\C-a)
195                   (setq newname (read-string (concat "Substitute old: "
196                                                      oldname
197                                                      ", new: ")
198                                              oldname))))
199        (if (or (equal newname "") (equal newname "$") (null newname))
200            (setq new (calc-top-n 1)
201                  expr (calc-top-n 2)
202                  num 2)
203          (setq new (if (stringp newname) (math-read-expr newname) newname))
204          (if (eq (car-safe new) 'error)
205              (error "Bad format in expression: %s" (nth 1 new)))
206          (setq expr (calc-top-n 1)))
207        (setq old (if (stringp oldname) (math-read-expr oldname) oldname))
208        (if (eq (car-safe old) 'error)
209            (error "Bad format in expression: %s" (nth 1 old)))
210        (or (math-expr-contains expr old)
211            (error "No occurrences found")))
212      (calc-enter-result num "sbst" (math-expr-subst expr old new)))))
213
214
215 (defun calc-has-rules (name)
216   (setq name (calc-var-value name))
217   (and (consp name)
218        (memq (car name) '(vec calcFunc-assign calcFunc-condition))
219        name))
220
221 ;; math-eval-rules-cache and math-eval-rules-cache-other are
222 ;; declared in calc.el, but are used here by math-recompile-eval-rules.
223 (defvar math-eval-rules-cache)
224 (defvar math-eval-rules-cache-other)
225
226 (defun math-recompile-eval-rules ()
227   (setq math-eval-rules-cache (and (calc-has-rules 'var-EvalRules)
228                                    (math-compile-rewrites
229                                     '(var EvalRules var-EvalRules)))
230         math-eval-rules-cache-other (assq nil math-eval-rules-cache)
231         math-eval-rules-cache-tag (calc-var-value 'var-EvalRules)))
232
233
234 ;;; Try to expand a formula according to its definition.
235 (defun math-expand-formula (expr)
236   (and (consp expr)
237        (symbolp (car expr))
238        (or (get (car expr) 'calc-user-defn)
239            (get (car expr) 'math-expandable))
240        (let ((res (let ((math-expand-formulas t))
241                     (apply (car expr) (cdr expr)))))
242          (and (not (eq (car-safe res) (car expr)))
243               res))))
244
245
246
247
248 ;;; True if A comes before B in a canonical ordering of expressions.  [P X X]
249 (defun math-beforep (a b)   ; [Public]
250   (cond ((and (Math-realp a) (Math-realp b))
251          (let ((comp (math-compare a b)))
252            (or (eq comp -1)
253                (and (eq comp 0)
254                     (not (equal a b))
255                     (> (length (memq (car-safe a)
256                                      '(bigneg nil bigpos frac float)))
257                        (length (memq (car-safe b)
258                                      '(bigneg nil bigpos frac float))))))))
259         ((equal b '(neg (var inf var-inf))) nil)
260         ((equal a '(neg (var inf var-inf))) t)
261         ((equal a '(var inf var-inf)) nil)
262         ((equal b '(var inf var-inf)) t)
263         ((Math-realp a)
264          (if (and (eq (car-safe b) 'intv) (math-intv-constp b))
265              (if (or (math-beforep a (nth 2 b)) (Math-equal a (nth 2 b)))
266                  t
267                nil)
268            t))
269         ((Math-realp b)
270          (if (and (eq (car-safe a) 'intv) (math-intv-constp a))
271              (if (math-beforep (nth 2 a) b)
272                  t
273                nil)
274            nil))
275         ((and (eq (car a) 'intv) (eq (car b) 'intv)
276               (math-intv-constp a) (math-intv-constp b))
277          (let ((comp (math-compare (nth 2 a) (nth 2 b))))
278            (cond ((eq comp -1) t)
279                  ((eq comp 1) nil)
280                  ((and (memq (nth 1 a) '(2 3)) (memq (nth 1 b) '(0 1))) t)
281                  ((and (memq (nth 1 a) '(0 1)) (memq (nth 1 b) '(2 3))) nil)
282                  ((eq (setq comp (math-compare (nth 3 a) (nth 3 b))) -1) t)
283                  ((eq comp 1) nil)
284                  ((and (memq (nth 1 a) '(0 2)) (memq (nth 1 b) '(1 3))) t)
285                  (t nil))))
286         ((not (eq (not (Math-objectp a)) (not (Math-objectp b))))
287          (Math-objectp a))
288         ((eq (car a) 'var)
289          (if (eq (car b) 'var)
290              (string-lessp (symbol-name (nth 1 a)) (symbol-name (nth 1 b)))
291            (not (Math-numberp b))))
292         ((eq (car b) 'var) (Math-numberp a))
293         ((eq (car a) (car b))
294          (while (and (setq a (cdr a) b (cdr b)) a
295                      (equal (car a) (car b))))
296          (and b
297               (or (null a)
298                   (math-beforep (car a) (car b)))))
299         (t (string-lessp (symbol-name (car a)) (symbol-name (car b))))))
300
301
302 (defsubst math-simplify-extended (a)
303   (let ((math-living-dangerously t))
304     (math-simplify a)))
305
306 (defalias 'calcFunc-esimplify 'math-simplify-extended)
307
308 ;; math-top-only is local to math-simplify, but is used by
309 ;; math-simplify-step, which is called by math-simplify.
310 (defvar math-top-only)
311
312 (defun math-simplify (top-expr)
313   (let ((math-simplifying t)
314         (math-top-only (consp calc-simplify-mode))
315         (simp-rules (append (and (calc-has-rules 'var-AlgSimpRules)
316                                  '((var AlgSimpRules var-AlgSimpRules)))
317                             (and math-living-dangerously
318                                  (calc-has-rules 'var-ExtSimpRules)
319                                  '((var ExtSimpRules var-ExtSimpRules)))
320                             (and math-simplifying-units
321                                  (calc-has-rules 'var-UnitSimpRules)
322                                  '((var UnitSimpRules var-UnitSimpRules)))
323                             (and math-integrating
324                                  (calc-has-rules 'var-IntegSimpRules)
325                                  '((var IntegSimpRules var-IntegSimpRules)))))
326         res)
327     (if math-top-only
328         (let ((r simp-rules))
329           (setq res (math-simplify-step (math-normalize top-expr))
330                 calc-simplify-mode '(nil)
331                 top-expr (math-normalize res))
332           (while r
333             (setq top-expr (math-rewrite top-expr (car r)
334                                          '(neg (var inf var-inf)))
335                   r (cdr r))))
336       (calc-with-default-simplification
337        (while (let ((r simp-rules))
338                 (setq res (math-normalize top-expr))
339                 (while r
340                   (setq res (math-rewrite res (car r))
341                         r (cdr r)))
342                 (not (equal top-expr (setq res (math-simplify-step res)))))
343          (setq top-expr res)))))
344   top-expr)
345
346 (defalias 'calcFunc-simplify 'math-simplify)
347
348 ;;; The following has a "bug" in that if any recursive simplifications
349 ;;; occur only the first handler will be tried; this doesn't really
350 ;;; matter, since math-simplify-step is iterated to a fixed point anyway.
351 (defun math-simplify-step (a)
352   (if (Math-primp a)
353       a
354     (let ((aa (if (or math-top-only
355                       (memq (car a) '(calcFunc-quote calcFunc-condition
356                                                      calcFunc-evalto)))
357                   a
358                 (cons (car a) (mapcar 'math-simplify-step (cdr a))))))
359       (and (symbolp (car aa))
360            (let ((handler (get (car aa) 'math-simplify)))
361              (and handler
362                   (while (and handler
363                               (equal (setq aa (or (funcall (car handler) aa)
364                                                   aa))
365                                      a))
366                     (setq handler (cdr handler))))))
367       aa)))
368
369
370 (defmacro math-defsimplify (funcs &rest code)
371   (append '(progn)
372           (mapcar (function
373                    (lambda (func)
374                      (list 'put (list 'quote func) ''math-simplify
375                            (list 'nconc
376                                  (list 'get (list 'quote func) ''math-simplify)
377                                  (list 'list
378                                        (list 'function
379                                              (append '(lambda (math-simplify-expr))
380                                                      code)))))))
381                   (if (symbolp funcs) (list funcs) funcs))))
382 (put 'math-defsimplify 'lisp-indent-hook 1)
383
384 ;; The function created by math-defsimplify uses the variable
385 ;; math-simplify-expr, and so is used by functions in math-defsimplify
386 (defvar math-simplify-expr)
387
388 (math-defsimplify (+ -)
389   (math-simplify-plus))
390
391 (defun math-simplify-plus ()
392   (cond ((and (memq (car-safe (nth 1 math-simplify-expr)) '(+ -))
393               (Math-numberp (nth 2 (nth 1 math-simplify-expr)))
394               (not (Math-numberp (nth 2 math-simplify-expr))))
395          (let ((x (nth 2 math-simplify-expr))
396                (op (car math-simplify-expr)))
397            (setcar (cdr (cdr math-simplify-expr)) (nth 2 (nth 1 math-simplify-expr)))
398            (setcar math-simplify-expr (car (nth 1 math-simplify-expr)))
399            (setcar (cdr (cdr (nth 1 math-simplify-expr))) x)
400            (setcar (nth 1 math-simplify-expr) op)))
401         ((and (eq (car math-simplify-expr) '+)
402               (Math-numberp (nth 1 math-simplify-expr))
403               (not (Math-numberp (nth 2 math-simplify-expr))))
404          (let ((x (nth 2 math-simplify-expr)))
405            (setcar (cdr (cdr math-simplify-expr)) (nth 1 math-simplify-expr))
406            (setcar (cdr math-simplify-expr) x))))
407   (let ((aa math-simplify-expr)
408         aaa temp)
409     (while (memq (car-safe (setq aaa (nth 1 aa))) '(+ -))
410       (if (setq temp (math-combine-sum (nth 2 aaa) (nth 2 math-simplify-expr)
411                                        (eq (car aaa) '-)
412                                        (eq (car math-simplify-expr) '-) t))
413           (progn
414             (setcar (cdr (cdr math-simplify-expr)) temp)
415             (setcar math-simplify-expr '+)
416             (setcar (cdr (cdr aaa)) 0)))
417       (setq aa (nth 1 aa)))
418     (if (setq temp (math-combine-sum aaa (nth 2 math-simplify-expr)
419                                      nil (eq (car math-simplify-expr) '-) t))
420         (progn
421           (setcar (cdr (cdr math-simplify-expr)) temp)
422           (setcar math-simplify-expr '+)
423           (setcar (cdr aa) 0)))
424     math-simplify-expr))
425
426 (math-defsimplify *
427   (math-simplify-times))
428
429 (defun math-simplify-times ()
430   (if (eq (car-safe (nth 2 math-simplify-expr)) '*)
431       (and (math-beforep (nth 1 (nth 2 math-simplify-expr)) (nth 1 math-simplify-expr))
432            (or (math-known-scalarp (nth 1 math-simplify-expr) t)
433                (math-known-scalarp (nth 1 (nth 2 math-simplify-expr)) t))
434            (let ((x (nth 1 math-simplify-expr)))
435              (setcar (cdr math-simplify-expr) (nth 1 (nth 2 math-simplify-expr)))
436              (setcar (cdr (nth 2 math-simplify-expr)) x)))
437     (and (math-beforep (nth 2 math-simplify-expr) (nth 1 math-simplify-expr))
438          (or (math-known-scalarp (nth 1 math-simplify-expr) t)
439              (math-known-scalarp (nth 2 math-simplify-expr) t))
440          (let ((x (nth 2 math-simplify-expr)))
441            (setcar (cdr (cdr math-simplify-expr)) (nth 1 math-simplify-expr))
442            (setcar (cdr math-simplify-expr) x))))
443   (let ((aa math-simplify-expr)
444         aaa temp
445         (safe t) (scalar (math-known-scalarp (nth 1 math-simplify-expr))))
446     (if (and (Math-ratp (nth 1 math-simplify-expr))
447              (setq temp (math-common-constant-factor (nth 2 math-simplify-expr))))
448         (progn
449           (setcar (cdr (cdr math-simplify-expr))
450                   (math-cancel-common-factor (nth 2 math-simplify-expr) temp))
451           (setcar (cdr math-simplify-expr) (math-mul (nth 1 math-simplify-expr) temp))))
452     (while (and (eq (car-safe (setq aaa (nth 2 aa))) '*)
453                 safe)
454       (if (setq temp (math-combine-prod (nth 1 math-simplify-expr)
455                                         (nth 1 aaa) nil nil t))
456           (progn
457             (setcar (cdr math-simplify-expr) temp)
458             (setcar (cdr aaa) 1)))
459       (setq safe (or scalar (math-known-scalarp (nth 1 aaa) t))
460             aa (nth 2 aa)))
461     (if (and (setq temp (math-combine-prod aaa (nth 1 math-simplify-expr) nil nil t))
462              safe)
463         (progn
464           (setcar (cdr math-simplify-expr) temp)
465           (setcar (cdr (cdr aa)) 1)))
466     (if (and (eq (car-safe (nth 1 math-simplify-expr)) 'frac)
467              (memq (nth 1 (nth 1 math-simplify-expr)) '(1 -1)))
468         (math-div (math-mul (nth 2 math-simplify-expr)
469                             (nth 1 (nth 1 math-simplify-expr)))
470                   (nth 2 (nth 1 math-simplify-expr)))
471       math-simplify-expr)))
472
473 (math-defsimplify /
474   (math-simplify-divide))
475
476 (defun math-simplify-divide ()
477   (let ((np (cdr math-simplify-expr))
478         (nover nil)
479         (nn (and (or (eq (car math-simplify-expr) '/)
480                      (not (Math-realp (nth 2 math-simplify-expr))))
481                  (math-common-constant-factor (nth 2 math-simplify-expr))))
482         n op)
483     (if nn
484         (progn
485           (setq n (and (or (eq (car math-simplify-expr) '/)
486                            (not (Math-realp (nth 1 math-simplify-expr))))
487                        (math-common-constant-factor (nth 1 math-simplify-expr))))
488           (if (and (eq (car-safe nn) 'frac) (eq (nth 1 nn) 1) (not n))
489               (progn
490                 (setcar (cdr math-simplify-expr)
491                         (math-mul (nth 2 nn) (nth 1 math-simplify-expr)))
492                 (setcar (cdr (cdr math-simplify-expr))
493                         (math-cancel-common-factor (nth 2 math-simplify-expr) nn))
494                 (if (and (math-negp nn)
495                          (setq op (assq (car math-simplify-expr) calc-tweak-eqn-table)))
496                     (setcar math-simplify-expr (nth 1 op))))
497             (if (and n (not (eq (setq n (math-frac-gcd n nn)) 1)))
498                 (progn
499                   (setcar (cdr math-simplify-expr)
500                           (math-cancel-common-factor (nth 1 math-simplify-expr) n))
501                   (setcar (cdr (cdr math-simplify-expr))
502                           (math-cancel-common-factor (nth 2 math-simplify-expr) n))
503                   (if (and (math-negp n)
504                            (setq op (assq (car math-simplify-expr)
505                                           calc-tweak-eqn-table)))
506                       (setcar math-simplify-expr (nth 1 op))))))))
507     (if (and (eq (car-safe (car np)) '/)
508              (math-known-scalarp (nth 2 math-simplify-expr) t))
509         (progn
510           (setq np (cdr (nth 1 math-simplify-expr)))
511           (while (eq (car-safe (setq n (car np))) '*)
512             (and (math-known-scalarp (nth 2 n) t)
513                  (math-simplify-divisor (cdr n) (cdr (cdr math-simplify-expr)) nil t))
514             (setq np (cdr (cdr n))))
515           (math-simplify-divisor np (cdr (cdr math-simplify-expr)) nil t)
516           (setq nover t
517                 np (cdr (cdr (nth 1 math-simplify-expr))))))
518     (while (eq (car-safe (setq n (car np))) '*)
519       (and (math-known-scalarp (nth 2 n) t)
520            (math-simplify-divisor (cdr n) (cdr (cdr math-simplify-expr)) nover t))
521       (setq np (cdr (cdr n))))
522     (math-simplify-divisor np (cdr (cdr math-simplify-expr)) nover t)
523     math-simplify-expr))
524
525 ;; The variables math-simplify-divisor-nover and math-simplify-divisor-dover
526 ;; are local variables for math-simplify-divisor, but are used by
527 ;; math-simplify-one-divisor.
528 (defvar math-simplify-divisor-nover)
529 (defvar math-simplify-divisor-dover)
530
531 (defun math-simplify-divisor (np dp math-simplify-divisor-nover
532                                  math-simplify-divisor-dover)
533   (cond ((eq (car-safe (car dp)) '/)
534          (math-simplify-divisor np (cdr (car dp))
535                                 math-simplify-divisor-nover
536                                 math-simplify-divisor-dover)
537          (and (math-known-scalarp (nth 1 (car dp)) t)
538               (math-simplify-divisor np (cdr (cdr (car dp)))
539                                      math-simplify-divisor-nover
540                                      (not math-simplify-divisor-dover))))
541         ((or (or (eq (car math-simplify-expr) '/)
542                  (let ((signs (math-possible-signs (car np))))
543                    (or (memq signs '(1 4))
544                        (and (memq (car math-simplify-expr) '(calcFunc-eq calcFunc-neq))
545                             (eq signs 5))
546                        math-living-dangerously)))
547              (math-numberp (car np)))
548          (let (d
549                (safe t)
550                (scalar (math-known-scalarp (car np))))
551            (while (and (eq (car-safe (setq d (car dp))) '*)
552                        safe)
553              (math-simplify-one-divisor np (cdr d))
554              (setq safe (or scalar (math-known-scalarp (nth 1 d) t))
555                    dp (cdr (cdr d))))
556            (if safe
557                (math-simplify-one-divisor np dp))))))
558
559 (defun math-simplify-one-divisor (np dp)
560   (let ((temp (math-combine-prod (car np) (car dp) math-simplify-divisor-nover
561                                  math-simplify-divisor-dover t))
562         op)
563     (if temp
564         (progn
565           (and (not (memq (car math-simplify-expr) '(/ calcFunc-eq calcFunc-neq)))
566                (math-known-negp (car dp))
567                (setq op (assq (car math-simplify-expr) calc-tweak-eqn-table))
568                (setcar math-simplify-expr (nth 1 op)))
569           (setcar np (if math-simplify-divisor-nover (math-div 1 temp) temp))
570           (setcar dp 1))
571       (and math-simplify-divisor-dover (not math-simplify-divisor-nover)
572            (eq (car math-simplify-expr) '/)
573            (eq (car-safe (car dp)) 'calcFunc-sqrt)
574            (Math-integerp (nth 1 (car dp)))
575            (progn
576              (setcar np (math-mul (car np)
577                                   (list 'calcFunc-sqrt (nth 1 (car dp)))))
578              (setcar dp (nth 1 (car dp))))))))
579
580 (defun math-common-constant-factor (expr)
581   (if (Math-realp expr)
582       (if (Math-ratp expr)
583           (and (not (memq expr '(0 1 -1)))
584                (math-abs expr))
585         (if (math-ratp (setq expr (math-to-simple-fraction expr)))
586             (math-common-constant-factor expr)))
587     (if (memq (car expr) '(+ - cplx sdev))
588         (let ((f1 (math-common-constant-factor (nth 1 expr)))
589               (f2 (math-common-constant-factor (nth 2 expr))))
590           (and f1 f2
591                (not (eq (setq f1 (math-frac-gcd f1 f2)) 1))
592                f1))
593       (if (memq (car expr) '(* polar))
594           (math-common-constant-factor (nth 1 expr))
595         (if (eq (car expr) '/)
596             (or (math-common-constant-factor (nth 1 expr))
597                 (and (Math-integerp (nth 2 expr))
598                      (list 'frac 1 (math-abs (nth 2 expr))))))))))
599
600 (defun math-cancel-common-factor (expr val)
601   (if (memq (car-safe expr) '(+ - cplx sdev))
602       (progn
603         (setcar (cdr expr) (math-cancel-common-factor (nth 1 expr) val))
604         (setcar (cdr (cdr expr)) (math-cancel-common-factor (nth 2 expr) val))
605         expr)
606     (if (eq (car-safe expr) '*)
607         (math-mul (math-cancel-common-factor (nth 1 expr) val) (nth 2 expr))
608       (math-div expr val))))
609
610 (defun math-frac-gcd (a b)
611   (if (Math-zerop a)
612       b
613     (if (Math-zerop b)
614         a
615       (if (and (Math-integerp a)
616                (Math-integerp b))
617           (math-gcd a b)
618         (and (Math-integerp a) (setq a (list 'frac a 1)))
619         (and (Math-integerp b) (setq b (list 'frac b 1)))
620         (math-make-frac (math-gcd (nth 1 a) (nth 1 b))
621                         (math-gcd (nth 2 a) (nth 2 b)))))))
622
623 (math-defsimplify %
624   (math-simplify-mod))
625
626 (defun math-simplify-mod ()
627   (and (Math-realp (nth 2 math-simplify-expr))
628        (Math-posp (nth 2 math-simplify-expr))
629        (let ((lin (math-is-linear (nth 1 math-simplify-expr)))
630              t1 t2 t3)
631          (or (and lin
632                   (or (math-negp (car lin))
633                       (not (Math-lessp (car lin) (nth 2 math-simplify-expr))))
634                   (list '%
635                         (list '+
636                               (math-mul (nth 1 lin) (nth 2 lin))
637                               (math-mod (car lin) (nth 2 math-simplify-expr)))
638                         (nth 2 math-simplify-expr)))
639              (and lin
640                   (not (math-equal-int (nth 1 lin) 1))
641                   (math-num-integerp (nth 1 lin))
642                   (math-num-integerp (nth 2 math-simplify-expr))
643                   (setq t1 (calcFunc-gcd (nth 1 lin) (nth 2 math-simplify-expr)))
644                   (not (math-equal-int t1 1))
645                   (list '*
646                         t1
647                         (list '%
648                               (list '+
649                                     (math-mul (math-div (nth 1 lin) t1)
650                                               (nth 2 lin))
651                                     (let ((calc-prefer-frac t))
652                                       (math-div (car lin) t1)))
653                               (math-div (nth 2 math-simplify-expr) t1))))
654              (and (math-equal-int (nth 2 math-simplify-expr) 1)
655                   (math-known-integerp (if lin
656                                            (math-mul (nth 1 lin) (nth 2 lin))
657                                          (nth 1 math-simplify-expr)))
658                   (if lin (math-mod (car lin) 1) 0))))))
659
660 (math-defsimplify (calcFunc-eq calcFunc-neq calcFunc-lt
661                                calcFunc-gt calcFunc-leq calcFunc-geq)
662   (if (= (length math-simplify-expr) 3)
663       (math-simplify-ineq)))
664
665 (defun math-simplify-ineq ()
666   (let ((np (cdr math-simplify-expr))
667         n)
668     (while (memq (car-safe (setq n (car np))) '(+ -))
669       (math-simplify-add-term (cdr (cdr n)) (cdr (cdr math-simplify-expr))
670                               (eq (car n) '-) nil)
671       (setq np (cdr n)))
672     (math-simplify-add-term np (cdr (cdr math-simplify-expr)) nil
673                             (eq np (cdr math-simplify-expr)))
674     (math-simplify-divide)
675     (let ((signs (math-possible-signs (cons '- (cdr math-simplify-expr)))))
676       (or (cond ((eq (car math-simplify-expr) 'calcFunc-eq)
677                  (or (and (eq signs 2) 1)
678                      (and (memq signs '(1 4 5)) 0)))
679                 ((eq (car math-simplify-expr) 'calcFunc-neq)
680                  (or (and (eq signs 2) 0)
681                      (and (memq signs '(1 4 5)) 1)))
682                 ((eq (car math-simplify-expr) 'calcFunc-lt)
683                  (or (and (eq signs 1) 1)
684                      (and (memq signs '(2 4 6)) 0)))
685                 ((eq (car math-simplify-expr) 'calcFunc-gt)
686                  (or (and (eq signs 4) 1)
687                      (and (memq signs '(1 2 3)) 0)))
688                 ((eq (car math-simplify-expr) 'calcFunc-leq)
689                  (or (and (eq signs 4) 0)
690                      (and (memq signs '(1 2 3)) 1)))
691                 ((eq (car math-simplify-expr) 'calcFunc-geq)
692                  (or (and (eq signs 1) 0)
693                      (and (memq signs '(2 4 6)) 1))))
694           math-simplify-expr))))
695
696 (defun math-simplify-add-term (np dp minus lplain)
697   (or (math-vectorp (car np))
698       (let ((rplain t)
699             n d dd temp)
700         (while (memq (car-safe (setq n (car np) d (car dp))) '(+ -))
701           (setq rplain nil)
702           (if (setq temp (math-combine-sum n (nth 2 d)
703                                            minus (eq (car d) '+) t))
704               (if (or lplain (eq (math-looks-negp temp) minus))
705                   (progn
706                     (setcar np (setq n (if minus (math-neg temp) temp)))
707                     (setcar (cdr (cdr d)) 0))
708                 (progn
709                   (setcar np 0)
710                   (setcar (cdr (cdr d)) (setq n (if (eq (car d) '+)
711                                                     (math-neg temp)
712                                                   temp))))))
713           (setq dp (cdr d)))
714         (if (setq temp (math-combine-sum n d minus t t))
715             (if (or lplain
716                     (and (not rplain)
717                          (eq (math-looks-negp temp) minus)))
718                 (progn
719                   (setcar np (setq n (if minus (math-neg temp) temp)))
720                   (setcar dp 0))
721               (progn
722                 (setcar np 0)
723                 (setcar dp (setq n (math-neg temp)))))))))
724
725 (math-defsimplify calcFunc-sin
726   (or (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arcsin)
727            (nth 1 (nth 1 math-simplify-expr)))
728       (and (math-looks-negp (nth 1 math-simplify-expr))
729            (math-neg (list 'calcFunc-sin (math-neg (nth 1 math-simplify-expr)))))
730       (and (eq calc-angle-mode 'rad)
731            (let ((n (math-linear-in (nth 1 math-simplify-expr) '(var pi var-pi))))
732              (and n
733                   (math-known-sin (car n) (nth 1 n) 120 0))))
734       (and (eq calc-angle-mode 'deg)
735            (let ((n (math-integer-plus (nth 1 math-simplify-expr))))
736              (and n
737                   (math-known-sin (car n) (nth 1 n) '(frac 2 3) 0))))
738       (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arccos)
739            (list 'calcFunc-sqrt (math-sub 1 (math-sqr
740                                              (nth 1 (nth 1 math-simplify-expr))))))
741       (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arctan)
742            (math-div (nth 1 (nth 1 math-simplify-expr))
743                      (list 'calcFunc-sqrt
744                            (math-add 1 (math-sqr
745                                         (nth 1 (nth 1 math-simplify-expr)))))))
746       (let ((m (math-should-expand-trig (nth 1 math-simplify-expr))))
747         (and m (integerp (car m))
748              (let ((n (car m)) (a (nth 1 m)))
749                (list '+
750                      (list '* (list 'calcFunc-sin (list '* (1- n) a))
751                            (list 'calcFunc-cos a))
752                      (list '* (list 'calcFunc-cos (list '* (1- n) a))
753                            (list 'calcFunc-sin a))))))))
754
755 (math-defsimplify calcFunc-cos
756   (or (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arccos)
757            (nth 1 (nth 1 math-simplify-expr)))
758       (and (math-looks-negp (nth 1 math-simplify-expr))
759            (list 'calcFunc-cos (math-neg (nth 1 math-simplify-expr))))
760       (and (eq calc-angle-mode 'rad)
761            (let ((n (math-linear-in (nth 1 math-simplify-expr) '(var pi var-pi))))
762              (and n
763                   (math-known-sin (car n) (nth 1 n) 120 300))))
764       (and (eq calc-angle-mode 'deg)
765            (let ((n (math-integer-plus (nth 1 math-simplify-expr))))
766              (and n
767                   (math-known-sin (car n) (nth 1 n) '(frac 2 3) 300))))
768       (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arcsin)
769            (list 'calcFunc-sqrt
770                  (math-sub 1 (math-sqr (nth 1 (nth 1 math-simplify-expr))))))
771       (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arctan)
772            (math-div 1
773                      (list 'calcFunc-sqrt
774                            (math-add 1
775                                      (math-sqr (nth 1 (nth 1 math-simplify-expr)))))))
776       (let ((m (math-should-expand-trig (nth 1 math-simplify-expr))))
777         (and m (integerp (car m))
778              (let ((n (car m)) (a (nth 1 m)))
779                (list '-
780                      (list '* (list 'calcFunc-cos (list '* (1- n) a))
781                            (list 'calcFunc-cos a))
782                      (list '* (list 'calcFunc-sin (list '* (1- n) a))
783                            (list 'calcFunc-sin a))))))))
784
785 (math-defsimplify calcFunc-sec
786   (or (and (math-looks-negp (nth 1 math-simplify-expr))
787            (list 'calcFunc-sec (math-neg (nth 1 math-simplify-expr))))
788       (and (eq calc-angle-mode 'rad)
789            (let ((n (math-linear-in (nth 1 math-simplify-expr) '(var pi var-pi))))
790              (and n
791                   (math-div 1 (math-known-sin (car n) (nth 1 n) 120 300)))))
792       (and (eq calc-angle-mode 'deg)
793            (let ((n (math-integer-plus (nth 1 math-simplify-expr))))
794              (and n
795                   (math-div 1 (math-known-sin (car n) (nth 1 n) '(frac 2 3) 300)))))
796       (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arcsin)
797            (math-div
798             1
799             (list 'calcFunc-sqrt
800                   (math-sub 1 (math-sqr (nth 1 (nth 1 math-simplify-expr)))))))
801       (and