Fix bug #4307: partswitch affects op and operatorp
[maxima.git] / src / opers.lisp
blob7b0bd2bf14436c63b2b65ef6cb2278c167235eae
1 ;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10 -*- ;;;;
2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3 ;;; The data in this file contains enhancements. ;;;;;
4 ;;; ;;;;;
5 ;;; Copyright (c) 1984,1987 by William Schelter,University of Texas ;;;;;
6 ;;; All rights reserved ;;;;;
7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8 ;;; (c) Copyright 1980 Massachusetts Institute of Technology ;;;
9 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
11 (in-package :maxima)
13 (macsyma-module opers)
15 ;; This file is the run-time half of the OPERS package, an interface to the
16 ;; Macsyma general representation simplifier. When new expressions are being
17 ;; created, the functions in this file or the macros in MOPERS should be called
18 ;; rather than the entrypoints in SIMP such as SIMPLIFYA or SIMPLUS. Many of
19 ;; the functions in this file will do a pre-simplification to prevent
20 ;; unnecessary consing. [Of course, this is really the "wrong" thing, since
21 ;; knowledge about 0 being the additive identity of the reals is now
22 ;; kept in two different places.]
24 ;; The basic functions in the virtual interface are ADD, SUB, MUL, DIV, POWER,
25 ;; NCMUL, NCPOWER, NEG, INV. Each of these functions assume that their
26 ;; arguments are simplified. Some functions will have a "*" adjoined to the
27 ;; end of the name (as in ADD*). These do not assume that their arguments are
28 ;; simplified. In addition, there are a few entrypoints such as ADDN, MULN
29 ;; which take a list of terms as a first argument, and a simplification flag as
30 ;; the second argument. The above functions are the only entrypoints to this
31 ;; package.
33 ;; The functions ADD2, ADD2*, MUL2, MUL2*, and MUL3 are for use internal to
34 ;; this package and should not be called externally. Note that MOPERS is
35 ;; needed to compile this file.
37 ;; Addition primitives.
39 (defun add2 (x y)
40 (cond ((numberp x)
41 (cond ((numberp y) (+ x y))
42 ((=0 x) y)
43 (t (simplifya `((mplus) ,x ,y) t))))
44 ((=0 y) x)
45 (t (simplifya `((mplus) ,x ,y) t))))
47 (defun add2* (x y)
48 (cond
49 ((and (numberp x) (numberp y)) (+ x y))
50 ((=0 x) (simplifya y nil))
51 ((=0 y) (simplifya x nil))
52 (t (simplifya `((mplus) ,x ,y) nil))))
54 ;; The first two cases in this cond shouldn't be needed, but exist
55 ;; for compatibility with the old OPERS package. The old ADDLIS
56 ;; deleted zeros ahead of time. Is this worth it?
58 (defun addn (terms simp-flag)
59 (cond ((null terms) 0)
60 (t (simplifya `((mplus) . ,terms) simp-flag))))
62 (defun neg (x)
63 (cond ((numberp x) (- x))
64 (t (let (($negdistrib t))
65 (simplifya `((mtimes) -1 ,x) t)))))
67 (defun sub (x y)
68 (cond
69 ((and (numberp x) (numberp y)) (- x y))
70 ((=0 y) x)
71 ((=0 x) (neg y))
72 (t (add x (neg y)))))
74 (defun sub* (x y)
75 (cond
76 ((and (numberp x) (numberp y)) (- x y))
77 ((=0 y) x)
78 ((=0 x) (neg y))
80 (add (simplifya x nil) (mul -1 (simplifya y nil))))))
82 ;; Multiplication primitives -- is it worthwhile to handle the 3-arg
83 ;; case specially? Don't simplify x*0 --> 0 since x could be non-scalar.
85 (defun mul2 (x y)
86 (cond
87 ((and (numberp x) (numberp y)) (* x y))
88 ((=1 x) y)
89 ((=1 y) x)
90 (t (simplifya `((mtimes) ,x ,y) t))))
92 (defun mul2* (x y)
93 (cond
94 ((and (numberp x) (numberp y)) (* x y))
95 ((=1 x) (simplifya y nil))
96 ((=1 y) (simplifya x nil))
97 (t (simplifya `((mtimes) ,x ,y) nil))))
99 (defun mul3 (x y z)
100 (cond ((=1 x) (mul2 y z))
101 ((=1 y) (mul2 x z))
102 ((=1 z) (mul2 x y))
103 (t (simplifya `((mtimes) ,x ,y ,z) t))))
105 ;; The first two cases in this cond shouldn't be needed, but exist
106 ;; for compatibility with the old OPERS package. The old MULSLIS
107 ;; deleted ones ahead of time. Is this worth it?
109 (defun muln (factors simp-flag)
110 (cond ((null factors) 1)
111 ((atom factors) factors)
112 (t (simplifya `((mtimes) . ,factors) simp-flag))))
114 (defun div (x y)
115 (if (=1 x)
116 (inv y)
117 (cond
118 ((and (floatp x) (floatp y))
119 (/ x y))
120 ((and ($bfloatp x) ($bfloatp y))
121 ;; Call BIGFLOATP to ensure that arguments have same precision.
122 ;; Otherwise FPQUOTIENT could return a spurious value.
123 (bcons (fpquotient (cdr (bigfloatp x)) (cdr (bigfloatp y)))))
125 (mul x (inv y))))))
127 (defun div* (x y)
128 (if (=1 x)
129 (inv* y)
130 (cond
131 ((and (floatp x) (floatp y))
132 (/ x y))
133 ((and ($bfloatp x) ($bfloatp y))
134 ;; Call BIGFLOATP to ensure that arguments have same precision.
135 ;; Otherwise FPQUOTIENT could return a spurious value.
136 (bcons (fpquotient (cdr (bigfloatp x)) (cdr (bigfloatp y)))))
138 (mul (simplifya x nil) (inv* y))))))
140 (defun ncmul2 (x y)
141 (simplifya `((mnctimes) ,x ,y) t))
143 (defun ncmuln (factors flag)
144 (simplifya `((mnctimes) . ,factors) flag))
146 ;; Exponentiation
148 ;; Don't use BASE as a parameter name since it is special in MacLisp.
150 (defun power (*base power)
151 (cond ((=1 power) *base)
152 (t (simplifya `((mexpt) ,*base ,power) t))))
154 (defun power* (*base power)
155 (cond ((=1 power) (simplifya *base nil))
156 (t (simplifya `((mexpt) ,*base ,power) nil))))
158 (defun ncpower (x y) (simplifya `((mncexpt) ,x ,y) t))
160 ;; [Add something for constructing equations here at some point.]
162 ;; (ROOT X N) takes the Nth root of X.
163 ;; Warning! Simplifier may give a complex expression back, starting from a
164 ;; positive (evidently) real expression, viz. sqrt[(sinh-sin) / (sin-sinh)] or
165 ;; something.
167 (defun root (x n)
168 (cond ((=0 x) 0)
169 ((=1 x) 1)
170 (t (simplifya `((mexpt) ,x ((rat simp) 1 ,n)) t))))
172 ;; (Porm flag expr) is +expr if flag is true, and -expr
173 ;; otherwise. Morp is the opposite. Names stand for "plus or minus"
174 ;; and vice versa.
176 (defun porm (s x) (if s x (neg x)))
177 (defun morp (s x) (if s (neg x) x))