X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/136211a997eb94f7dc6f97219052317116e114da..47854a55680b5809811caf72f66ecbe8289c2855:/lisp/calc/calc-poly.el diff --git a/lisp/calc/calc-poly.el b/lisp/calc/calc-poly.el index eba14b7d62..de2cf2e016 100644 --- a/lisp/calc/calc-poly.el +++ b/lisp/calc/calc-poly.el @@ -1,34 +1,37 @@ -;; Calculator for GNU Emacs, part II [calc-poly.el] -;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc. -;; Written by Dave Gillespie, daveg@synaptics.com. +;;; calc-poly.el --- polynomial functions for Calc + +;; Copyright (C) 1990, 1991, 1992, 1993, 2001, 2002, 2003, 2004, +;; 2005, 2006, 2007 Free Software Foundation, Inc. + +;; Author: David Gillespie +;; Maintainer: Jay Belanger ;; This file is part of GNU Emacs. +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + ;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY. No author or distributor -;; accepts responsibility to anyone for the consequences of using it -;; or for whether it serves any particular purpose or works at all, -;; unless he says so in writing. Refer to the GNU Emacs General Public -;; License for full details. +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. -;; Everyone is granted permission to copy, modify and redistribute -;; GNU Emacs, but only under the conditions described in the -;; GNU Emacs General Public License. A copy of this license is -;; supposed to have been given to you along with GNU Emacs so you -;; can know your rights and responsibilities. It should be in a -;; file named COPYING. Among other things, the copyright notice -;; and this notice must be preserved on all copies. +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. +;;; Commentary: +;;; Code: ;; This file is autoloaded from calc-ext.el. -(require 'calc-ext) +(require 'calc-ext) (require 'calc-macs) -(defun calc-Need-calc-poly () nil) - - (defun calcFunc-pcont (expr &optional var) (cond ((Math-primp expr) (cond ((Math-zerop expr) 1) @@ -65,23 +68,20 @@ (math-neg (math-poly-gcd cont c2)) (math-poly-gcd cont c2)))))) (var expr) - (t 1)) -) + (t 1))) (defun calcFunc-pprim (expr &optional var) (let ((cont (calcFunc-pcont expr var))) (if (math-equal-int cont 1) expr - (math-poly-div-exact expr cont var))) -) + (math-poly-div-exact expr cont var)))) (defun math-div-poly-const (expr c) (cond ((memq (car-safe expr) '(+ -)) (list (car expr) (math-div-poly-const (nth 1 expr) c) (math-div-poly-const (nth 2 expr) c))) - (t (math-div expr c))) -) + (t (math-div expr c)))) (defun calcFunc-pdeg (expr &optional var) (if (Math-zerop expr) @@ -89,8 +89,7 @@ (if var (or (math-polynomial-p expr var) (math-reject-arg expr "Expected a polynomial")) - (math-poly-degree expr))) -) + (math-poly-degree expr)))) (defun math-poly-degree (expr) (cond ((Math-primp expr) @@ -108,8 +107,7 @@ ((memq (car expr) '(+ -)) (max (math-poly-degree (nth 1 expr)) (math-poly-degree (nth 2 expr)))) - (t 1)) -) + (t 1))) (defun calcFunc-plead (expr var) (cond ((eq (car-safe expr) '*) @@ -128,8 +126,7 @@ (let ((p (math-is-polynomial expr var))) (if (cdr p) (nth (1- (length p)) p) - 1)))) -) + 1))))) @@ -139,7 +136,7 @@ ;;; Originally by Ove Ewerlid (ewerlid@mizar.DoCS.UU.SE). ;;; Modifications and simplifications by daveg. -(setq math-poly-modulus 1) +(defvar math-poly-modulus 1) ;;; Return gcd of two polynomials (defun calcFunc-pgcd (pn pd) @@ -149,38 +146,39 @@ (math-reject-arg pd "Coefficients must be rational")) (let ((calc-prefer-frac t) (math-poly-modulus (math-poly-modulus pn pd))) - (math-poly-gcd pn pd)) -) + (math-poly-gcd pn pd))) ;;; Return only quotient to top of stack (nil if zero) + +;; calc-poly-div-remainder is a local variable for +;; calc-poly-div (in calc-alg.el), but is used by +;; calcFunc-pdiv, which is called by calc-poly-div. +(defvar calc-poly-div-remainder) + (defun calcFunc-pdiv (pn pd &optional base) (let* ((calc-prefer-frac t) (math-poly-modulus (math-poly-modulus pn pd)) (res (math-poly-div pn pd base))) (setq calc-poly-div-remainder (cdr res)) - (car res)) -) + (car res))) ;;; Return only remainder to top of stack (defun calcFunc-prem (pn pd &optional base) (let ((calc-prefer-frac t) (math-poly-modulus (math-poly-modulus pn pd))) - (cdr (math-poly-div pn pd base))) -) + (cdr (math-poly-div pn pd base)))) (defun calcFunc-pdivrem (pn pd &optional base) (let* ((calc-prefer-frac t) (math-poly-modulus (math-poly-modulus pn pd)) (res (math-poly-div pn pd base))) - (list 'vec (car res) (cdr res))) -) + (list 'vec (car res) (cdr res)))) (defun calcFunc-pdivide (pn pd &optional base) (let* ((calc-prefer-frac t) (math-poly-modulus (math-poly-modulus pn pd)) (res (math-poly-div pn pd base))) - (math-add (car res) (math-div (cdr res) pd))) -) + (math-add (car res) (math-div (cdr res) pd)))) ;;; Multiply two terms, expanding out products of sums. @@ -193,16 +191,14 @@ (list (car rhs) (math-mul-thru lhs (nth 1 rhs)) (math-mul-thru lhs (nth 2 rhs))) - (math-mul lhs rhs))) -) + (math-mul lhs rhs)))) (defun math-div-thru (num den) (if (memq (car-safe num) '(+ -)) (list (car num) (math-div-thru (nth 1 num) den) (math-div-thru (nth 2 num) den)) - (math-div num den)) -) + (math-div num den))) ;;; Sort the terms of a sum into canonical order. @@ -211,8 +207,7 @@ (math-list-to-sum (sort (math-sum-to-list expr) (function (lambda (a b) (math-beforep (car a) (car b)))))) - expr) -) + expr)) (defun math-list-to-sum (lst) (if (cdr lst) @@ -221,8 +216,7 @@ (car (car lst))) (if (cdr (car lst)) (math-neg (car (car lst))) - (car (car lst)))) -) + (car (car lst))))) (defun math-sum-to-list (tree &optional neg) (cond ((eq (car-safe tree) '+) @@ -231,39 +225,34 @@ ((eq (car-safe tree) '-) (nconc (math-sum-to-list (nth 1 tree) neg) (math-sum-to-list (nth 2 tree) (not neg)))) - (t (list (cons tree neg)))) -) + (t (list (cons tree neg))))) ;;; Check if the polynomial coefficients are modulo forms. (defun math-poly-modulus (expr &optional expr2) (or (math-poly-modulus-rec expr) (and expr2 (math-poly-modulus-rec expr2)) - 1) -) + 1)) (defun math-poly-modulus-rec (expr) (if (and (eq (car-safe expr) 'mod) (Math-natnump (nth 2 expr))) (list 'mod 1 (nth 2 expr)) (and (memq (car-safe expr) '(+ - * /)) (or (math-poly-modulus-rec (nth 1 expr)) - (math-poly-modulus-rec (nth 2 expr))))) -) + (math-poly-modulus-rec (nth 2 expr)))))) ;;; Divide two polynomials. Return (quotient . remainder). +(defvar math-poly-div-base nil) (defun math-poly-div (u v &optional math-poly-div-base) (if math-poly-div-base (math-do-poly-div u v) - (math-do-poly-div (calcFunc-expand u) (calcFunc-expand v))) -) -(setq math-poly-div-base nil) + (math-do-poly-div (calcFunc-expand u) (calcFunc-expand v)))) (defun math-poly-div-exact (u v &optional base) (let ((res (math-poly-div u v base))) (if (eq (cdr res) 0) (car res) - (math-reject-arg (list 'vec u v) "Argument is not a polynomial"))) -) + (math-reject-arg (list 'vec u v) "Argument is not a polynomial")))) (defun math-do-poly-div (u v) (cond ((math-constp u) @@ -293,8 +282,7 @@ (setq up (math-is-polynomial u base nil 'gen) res (math-poly-div-coefs up vp)) (cons (math-build-polynomial-expr (car res) base) - (math-build-polynomial-expr (cdr res) base)))))) -) + (math-build-polynomial-expr (cdr res) base))))))) (defun math-poly-div-rec (u v) (cond ((math-constp u) @@ -322,8 +310,7 @@ res (math-poly-div-coefs up vp)) (math-add (math-build-polynomial-expr (car res) base) (math-div (math-build-polynomial-expr (cdr res) base) - v)))))) -) + v))))))) ;;; Divide two polynomials in coefficient-list form. Return (quot . rem). (defun math-poly-div-coefs (u v) @@ -349,8 +336,7 @@ (cons q (nreverse (mapcar 'math-simplify urev))))) (t (cons (list (math-poly-div-rec (car u) (car v))) - nil))) -) + nil)))) ;;; Perform a pseudo-division of polynomials. (See Knuth section 4.6.1.) ;;; This returns only the remainder from the pseudo-division. @@ -375,8 +361,7 @@ (while (and urev (Math-zerop (car urev))) (setq urev (cdr urev))) (nreverse (mapcar 'math-simplify urev)))) - (t nil)) -) + (t nil))) ;;; Compute the GCD of two multivariate polynomials. (defun math-poly-gcd (u v) @@ -398,16 +383,14 @@ (math-poly-gcd-coefs (math-is-polynomial u base nil 'gen) (math-is-polynomial v base nil 'gen)) base))) - (calcFunc-gcd (calcFunc-pcont u) (calcFunc-pcont u)))))) -) + (calcFunc-gcd (calcFunc-pcont u) (calcFunc-pcont u))))))) (defun math-poly-div-list (lst a) (if (eq a 1) lst (if (eq a -1) (math-mul-list lst a) - (mapcar (function (lambda (x) (math-poly-div-exact x a))) lst))) -) + (mapcar (function (lambda (x) (math-poly-div-exact x a))) lst)))) (defun math-mul-list (lst a) (if (eq a 1) @@ -415,8 +398,7 @@ (if (eq a -1) (mapcar 'math-neg lst) (and (not (eq a 0)) - (mapcar (function (lambda (x) (math-mul x a))) lst)))) -) + (mapcar (function (lambda (x) (math-mul x a))) lst))))) ;;; Run GCD on all elements in a list. (defun math-poly-gcd-list (lst) @@ -427,8 +409,7 @@ (or (eq (car lst) 0) (setq gcd (math-poly-gcd gcd (car lst))))) (if lst (setq lst (math-poly-gcd-frac-list lst))) - gcd)) -) + gcd))) (defun math-poly-gcd-frac-list (lst) (while (and lst (not (eq (car-safe (car lst)) 'frac))) @@ -439,8 +420,7 @@ (if (eq (car-safe (car lst)) 'frac) (setq denom (calcFunc-lcm denom (nth 2 (car lst)))))) (list 'frac 1 denom)) - 1) -) + 1)) ;;; Compute the GCD of two monovariate polynomial lists. ;;; Knuth section 4.6.1, algorithm C. @@ -473,8 +453,7 @@ (setq v (math-mul-list v -1))) (while (>= (setq z (1- z)) 0) (setq v (cons 0 v))) - v) -) + v)) ;;; Return true if is a factor containing no sums or quotients. @@ -486,8 +465,7 @@ nil) ((memq (car-safe expr) '(^ neg)) (math-atomic-factorp (nth 1 expr))) - (t t)) -) + (t t))) ;;; Find a suitable base for dividing a by b. ;;; The base must exist in both expressions. @@ -506,8 +484,7 @@ (if maybe (if (>= (nth 1 (car a-base)) (nth 1 maybe)) (throw 'return (car (car a-base)))))) - (setq a-base (cdr a-base)))))) -) + (setq a-base (cdr a-base))))))) ;;; Same as above but for gcd algorithm. ;;; Here there is no requirement that degree(a) > degree(b). @@ -526,93 +503,108 @@ (setq a-base (cdr a-base))) (if (assoc (car (car b-base)) a-base) (throw 'return (car (car b-base))) - (setq b-base (cdr b-base)))))))) -) + (setq b-base (cdr b-base))))))))) ;;; Sort a list of polynomial bases. (defun math-sort-poly-base-list (lst) (sort lst (function (lambda (a b) (or (> (nth 1 a) (nth 1 b)) (and (= (nth 1 a) (nth 1 b)) - (math-beforep (car a) (car b))))))) -) + (math-beforep (car a) (car b)))))))) ;;; Given an expression find all variables that are polynomial bases. ;;; Return list in the form '( (var1 degree1) (var2 degree2) ... ). -;;; Note dynamic scope of mpb-total-base. + +;; The variable math-poly-base-total-base is local to +;; math-total-polynomial-base, but is used by math-polynomial-p1, +;; which is called by math-total-polynomial-base. +(defvar math-poly-base-total-base) + (defun math-total-polynomial-base (expr) - (let ((mpb-total-base nil)) + (let ((math-poly-base-total-base nil)) (math-polynomial-base expr 'math-polynomial-p1) - (math-sort-poly-base-list mpb-total-base)) -) + (math-sort-poly-base-list math-poly-base-total-base))) + +;; The variable math-poly-base-top-expr is local to math-polynomial-base +;; in calc-alg.el, but is used by math-polynomial-p1 which is called +;; by math-polynomial-base. +(defvar math-poly-base-top-expr) (defun math-polynomial-p1 (subexpr) - (or (assoc subexpr mpb-total-base) + (or (assoc subexpr math-poly-base-total-base) (memq (car subexpr) '(+ - * / neg)) (and (eq (car subexpr) '^) (natnump (nth 2 subexpr))) (let* ((math-poly-base-variable subexpr) - (exponent (math-polynomial-p mpb-top-expr subexpr))) + (exponent (math-polynomial-p math-poly-base-top-expr subexpr))) (if exponent - (setq mpb-total-base (cons (list subexpr exponent) - mpb-total-base))))) - nil -) - - - - -(defun calcFunc-factors (expr &optional var) + (setq math-poly-base-total-base (cons (list subexpr exponent) + math-poly-base-total-base))))) + nil) + +;; The variable math-factored-vars is local to calcFunc-factors and +;; calcFunc-factor, but is used by math-factor-expr and +;; math-factor-expr-part, which are called (directly and indirectly) by +;; calcFunc-factor and calcFunc-factors. +(defvar math-factored-vars) + +;; The variable math-fact-expr is local to calcFunc-factors, +;; calcFunc-factor and math-factor-expr, but is used by math-factor-expr-try +;; and math-factor-expr-part, which are called (directly and indirectly) by +;; calcFunc-factor, calcFunc-factors and math-factor-expr. +(defvar math-fact-expr) + +;; The variable math-to-list is local to calcFunc-factors and +;; calcFunc-factor, but is used by math-accum-factors, which is +;; called (indirectly) by calcFunc-factors and calcFunc-factor. +(defvar math-to-list) + +(defun calcFunc-factors (math-fact-expr &optional var) (let ((math-factored-vars (if var t nil)) (math-to-list t) (calc-prefer-frac t)) (or var - (setq var (math-polynomial-base expr))) + (setq var (math-polynomial-base math-fact-expr))) (let ((res (math-factor-finish (or (catch 'factor (math-factor-expr-try var)) - expr)))) + math-fact-expr)))) (math-simplify (if (math-vectorp res) res - (list 'vec (list 'vec res 1)))))) -) + (list 'vec (list 'vec res 1))))))) -(defun calcFunc-factor (expr &optional var) +(defun calcFunc-factor (math-fact-expr &optional var) (let ((math-factored-vars nil) (math-to-list nil) (calc-prefer-frac t)) (math-simplify (math-factor-finish (if var (let ((math-factored-vars t)) - (or (catch 'factor (math-factor-expr-try var)) expr)) - (math-factor-expr expr))))) -) + (or (catch 'factor (math-factor-expr-try var)) math-fact-expr)) + (math-factor-expr math-fact-expr)))))) (defun math-factor-finish (x) (if (Math-primp x) x (if (eq (car x) 'calcFunc-Fac-Prot) (math-factor-finish (nth 1 x)) - (cons (car x) (mapcar 'math-factor-finish (cdr x))))) -) + (cons (car x) (mapcar 'math-factor-finish (cdr x)))))) (defun math-factor-protect (x) (if (memq (car-safe x) '(+ -)) (list 'calcFunc-Fac-Prot x) - x) -) - -(defun math-factor-expr (expr) - (cond ((eq math-factored-vars t) expr) - ((or (memq (car-safe expr) '(* / ^ neg)) - (assq (car-safe expr) calc-tweak-eqn-table)) - (cons (car expr) (mapcar 'math-factor-expr (cdr expr)))) - ((memq (car-safe expr) '(+ -)) + x)) + +(defun math-factor-expr (math-fact-expr) + (cond ((eq math-factored-vars t) math-fact-expr) + ((or (memq (car-safe math-fact-expr) '(* / ^ neg)) + (assq (car-safe math-fact-expr) calc-tweak-eqn-table)) + (cons (car math-fact-expr) (mapcar 'math-factor-expr (cdr math-fact-expr)))) + ((memq (car-safe math-fact-expr) '(+ -)) (let* ((math-factored-vars math-factored-vars) - (y (catch 'factor (math-factor-expr-part expr)))) + (y (catch 'factor (math-factor-expr-part math-fact-expr)))) (if y (math-factor-expr y) - expr))) - (t expr)) -) + math-fact-expr))) + (t math-fact-expr))) (defun math-factor-expr-part (x) ; uses "expr" (if (memq (car-safe x) '(+ - * / ^ neg)) @@ -620,27 +612,29 @@ (math-factor-expr-part (car x))) (and (not (Math-objvecp x)) (not (assoc x math-factored-vars)) - (> (math-factor-contains expr x) 1) + (> (math-factor-contains math-fact-expr x) 1) (setq math-factored-vars (cons (list x) math-factored-vars)) - (math-factor-expr-try x))) -) - -(defun math-factor-expr-try (x) - (if (eq (car-safe expr) '*) - (let ((res1 (catch 'factor (let ((expr (nth 1 expr))) - (math-factor-expr-try x)))) - (res2 (catch 'factor (let ((expr (nth 2 expr))) - (math-factor-expr-try x))))) + (math-factor-expr-try x)))) + +;; The variable math-fet-x is local to math-factor-expr-try, but is +;; used by math-factor-poly-coefs, which is called by math-factor-expr-try. +(defvar math-fet-x) + +(defun math-factor-expr-try (math-fet-x) + (if (eq (car-safe math-fact-expr) '*) + (let ((res1 (catch 'factor (let ((math-fact-expr (nth 1 math-fact-expr))) + (math-factor-expr-try math-fet-x)))) + (res2 (catch 'factor (let ((math-fact-expr (nth 2 math-fact-expr))) + (math-factor-expr-try math-fet-x))))) (and (or res1 res2) - (throw 'factor (math-accum-factors (or res1 (nth 1 expr)) 1 - (or res2 (nth 2 expr)))))) - (let* ((p (math-is-polynomial expr x 30 'gen)) - (math-poly-modulus (math-poly-modulus expr)) + (throw 'factor (math-accum-factors (or res1 (nth 1 math-fact-expr)) 1 + (or res2 (nth 2 math-fact-expr)))))) + (let* ((p (math-is-polynomial math-fact-expr math-fet-x 30 'gen)) + (math-poly-modulus (math-poly-modulus math-fact-expr)) res) (and (cdr p) (setq res (math-factor-poly-coefs p)) - (throw 'factor res)))) -) + (throw 'factor res))))) (defun math-accum-factors (fac pow facs) (if math-to-list @@ -671,15 +665,14 @@ (cons 'vec (cons (nth 1 facs) (cons (list 'vec fac pow) (cdr (cdr facs))))) (cons 'vec (cons (list 'vec fac pow) (cdr facs)))))))) - (math-mul (math-pow fac pow) facs)) -) + (math-mul (math-pow fac pow) facs))) (defun math-factor-poly-coefs (p &optional square-free) ; uses "x" - (let (t1 t2) + (let (t1 t2 temp) (cond ((not (cdr p)) (or (car p) 0)) - ;; Strip off multiples of x. + ;; Strip off multiples of math-fet-x. ((Math-zerop (car p)) (let ((z 0)) (while (and p (Math-zerop (car p))) @@ -687,7 +680,7 @@ (if (cdr p) (setq p (math-factor-poly-coefs p square-free)) (setq p (math-sort-terms (math-factor-expr (car p))))) - (math-accum-factors x z (math-factor-protect p)))) + (math-accum-factors math-fet-x z (math-factor-protect p)))) ;; Factor out content. ((and (not square-free) @@ -698,14 +691,15 @@ (math-accum-factors t1 1 (math-factor-poly-coefs (math-poly-div-list p t1) 'cont))) - ;; Check if linear in x. + ;; Check if linear in math-fet-x. ((not (cdr (cdr p))) - (math-add (math-factor-protect - (math-sort-terms - (math-factor-expr (car p)))) - (math-mul x (math-factor-protect - (math-sort-terms - (math-factor-expr (nth 1 p))))))) + (math-sort-terms + (math-add (math-factor-protect + (math-sort-terms + (math-factor-expr (car p)))) + (math-mul math-fet-x (math-factor-protect + (math-sort-terms + (math-factor-expr (nth 1 p)))))))) ;; If symbolic coefficients, use FactorRules. ((let ((pp p)) @@ -716,7 +710,7 @@ (setq pp (cdr pp))) pp) (let ((res (math-rewrite - (list 'calcFunc-thecoefs x (cons 'vec p)) + (list 'calcFunc-thecoefs math-fet-x (cons 'vec p)) '(var FactorRules var-FactorRules)))) (or (and (eq (car-safe res) 'calcFunc-thefactors) (= (length res) 3) @@ -726,7 +720,7 @@ (while (setq vec (cdr vec)) (setq facs (math-accum-factors (car vec) 1 facs))) facs)) - (math-build-polynomial-expr p x)))) + (math-build-polynomial-expr p math-fet-x)))) ;; Check if rational coefficients (i.e., not modulo a prime). ((eq math-poly-modulus 1) @@ -757,12 +751,13 @@ (setq scale (math-div scale den)) (math-add (math-add - (math-mul den (math-pow x 2)) - (math-mul (math-mul coef1 den) x)) + (math-mul den (math-pow math-fet-x 2)) + (math-mul (math-mul coef1 den) + math-fet-x)) (math-mul coef0 den))) (let ((den (math-lcm-denoms coef0))) (setq scale (math-div scale den)) - (math-add (math-mul den x) + (math-add (math-mul den math-fet-x) (math-mul coef0 den)))) 1 expr) roots (cdr roots)))) @@ -771,8 +766,8 @@ (math-mul csign (math-build-polynomial-expr (math-mul-list (nth 1 t1) scale) - x))))) - (math-build-polynomial-expr p x)) ; can't factor it. + math-fet-x))))) + (math-build-polynomial-expr p math-fet-x)) ; can't factor it. ;; Separate out the squared terms (Knuth exercise 4.6.2-34). ;; This step also divides out the content of the polynomial. @@ -813,8 +808,7 @@ (and (setq temp (math-factor-poly-coefs p)) (math-pow temp (nth 2 math-poly-modulus)))) (t - (math-reject-arg nil "*Modulo factorization not yet implemented")))) -) + (math-reject-arg nil "*Modulo factorization not yet implemented"))))) (defun math-poly-deriv-coefs (p) (let ((n 1) @@ -822,8 +816,7 @@ (while (setq p (cdr p)) (setq dp (cons (math-mul (car p) n) dp) n (1+ n))) - (nreverse dp)) -) + (nreverse dp))) (defun math-factor-contains (x a) (if (equal x a) @@ -836,8 +829,7 @@ (if (and (eq (car-safe x) '^) (natnump (nth 2 x))) (* (math-factor-contains (nth 1 x) a) (nth 2 x)) - 0))) -) + 0)))) @@ -860,14 +852,12 @@ (den2 (math-poly-div den g))) (and (eq (cdr num2) 0) (eq (cdr den2) 0) (setq num (car num2) den (car den2))))) - (math-simplify (math-div num den)))) -) + (math-simplify (math-div num den))))) ;;; Returns expressions (num . denom). (defun math-to-ratpoly (expr) (let ((res (math-to-ratpoly-rec expr))) - (cons (math-simplify (car res)) (math-simplify (cdr res)))) -) + (cons (math-simplify (car res)) (math-simplify (cdr res))))) (defun math-to-ratpoly-rec (expr) (cond ((Math-primp expr) @@ -933,8 +923,7 @@ ((eq (car expr) 'neg) (let ((r1 (math-to-ratpoly-rec (nth 1 expr)))) (cons (math-neg (car r1)) (cdr r1)))) - (t (cons expr 1))) -) + (t (cons expr 1)))) (defun math-ratpoly-p (expr &optional var) @@ -963,8 +952,7 @@ (and p1 (* p1 (nth 2 expr))))) ((not var) 1) ((math-poly-depends expr var) nil) - (t 0)) -) + (t 0))) (defun calcFunc-apart (expr &optional var) @@ -990,16 +978,20 @@ (math-add q (or (and var (math-expr-contains den var) (math-partial-fractions r den var)) - (math-div r den)))))) -) + (math-div r den))))))) (defun math-padded-polynomial (expr var deg) + "Return a polynomial as list of coefficients. +If EXPR is of the form \"a + bx + cx^2 + ...\" in the variable VAR, return +the list (a b c ...) with at least DEG elements, else return NIL." (let ((p (math-is-polynomial expr var deg))) - (append p (make-list (- deg (length p)) 0))) -) + (append p (make-list (- deg (length p)) 0)))) (defun math-partial-fractions (r den var) + "Return R divided by DEN expressed in partial fractions of VAR. +All whole factors of DEN have already been split off from R. +If no partial fraction representation can be found, return nil." (let* ((fden (calcFunc-factors den var)) (tdeg (math-polynomial-p den var)) (fp fden) @@ -1063,8 +1055,7 @@ res (math-add res (math-div num (car dlist))) num nil)) (setq dlist (cdr dlist))) - (math-normalize res)))))) -) + (math-normalize res))))))) @@ -1087,21 +1078,39 @@ ((and (eq (car-safe expr) '^) (memq (car-safe (nth 1 expr)) '(+ -)) (integerp (nth 2 expr)) - (if (> (nth 2 expr) 0) - (or (and (or (> mmt-many 500000) (< mmt-many -500000)) - (math-expand-power (nth 1 expr) (nth 2 expr) - nil t)) - (list '* - (nth 1 expr) - (list '^ (nth 1 expr) (1- (nth 2 expr))))) - (if (< (nth 2 expr) 0) - (list '/ 1 (list '^ (nth 1 expr) (- (nth 2 expr)))))))) - (t expr)) -) + (if (and + (or (math-known-matrixp (nth 1 (nth 1 expr))) + (math-known-matrixp (nth 2 (nth 1 expr))) + (and + calc-matrix-mode + (not (eq calc-matrix-mode 'scalar)) + (not (and (math-known-scalarp (nth 1 (nth 1 expr))) + (math-known-scalarp (nth 2 (nth 1 expr))))))) + (> (nth 2 expr) 1)) + (if (= (nth 2 expr) 2) + (math-add-or-sub (list '* (nth 1 (nth 1 expr)) (nth 1 expr)) + (list '* (nth 2 (nth 1 expr)) (nth 1 expr)) + nil (eq (car (nth 1 expr)) '-)) + (math-add-or-sub (list '* (nth 1 (nth 1 expr)) + (list '^ (nth 1 expr) + (1- (nth 2 expr)))) + (list '* (nth 2 (nth 1 expr)) + (list '^ (nth 1 expr) + (1- (nth 2 expr)))) + nil (eq (car (nth 1 expr)) '-))) + (if (> (nth 2 expr) 0) + (or (and (or (> math-mt-many 500000) (< math-mt-many -500000)) + (math-expand-power (nth 1 expr) (nth 2 expr) + nil t)) + (list '* + (nth 1 expr) + (list '^ (nth 1 expr) (1- (nth 2 expr))))) + (if (< (nth 2 expr) 0) + (list '/ 1 (list '^ (nth 1 expr) (- (nth 2 expr))))))))) + (t expr))) (defun calcFunc-expand (expr &optional many) - (math-normalize (math-map-tree 'math-expand-term expr many)) -) + (math-normalize (math-map-tree 'math-expand-term expr many))) (defun math-expand-power (x n &optional var else-nil) (or (and (natnump n) @@ -1184,12 +1193,12 @@ (setq p1 (cdr p1))) accum)))))) (and (not else-nil) - (list '^ x n))) -) + (list '^ x n)))) (defun calcFunc-expandpow (x n) - (math-normalize (math-expand-power x n)) -) - + (math-normalize (math-expand-power x n))) +(provide 'calc-poly) +;;; arch-tag: d2566c51-2ccc-45f1-8c50-f3462c2953ff +;;; calc-poly.el ends here