close Warning: Can't synchronize with repository "(default)" (The repository directory has changed, you should resynchronize the repository with: trac-admin $ENV repository resync '(default)'). Look in the Trac log for more information.

source: branches/f4grobner/polynomial-eval.lisp

Last change on this file was 4463, checked in by Marek Rychlik, 8 years ago
File size: 3.4 KB
Line 
1;;; -*- Mode: Lisp -*-
2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3;;;
4;;; Copyright (C) 1999, 2002, 2009, 2015 Marek Rychlik <rychlik@u.arizona.edu>
5;;;
6;;; This program is free software; you can redistribute it and/or modify
7;;; it under the terms of the GNU General Public License as published by
8;;; the Free Software Foundation; either version 2 of the License, or
9;;; (at your option) any later version.
10;;;
11;;; This program is distributed in the hope that it will be useful,
12;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14;;; GNU General Public License for more details.
15;;;
16;;; You should have received a copy of the GNU General Public License
17;;; along with this program; if not, write to the Free Software
18;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19;;;
20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
21
22(in-package "POLYNOMIAL")
23
24(defvar *coefficient-class* 'integer-ring
25 "The default class in which coefficients are created from
26NUMBER tokens.")
27
28(defun poly-eval (expr vars order &optional (coefficient-class *coefficient-class*))
29 "Evaluate Lisp form EXPR to a polynomial or a list of polynomials in
30variables VARS. Return the resulting polynomial or list of
31polynomials. Standard arithmetical operators in form EXPR are
32replaced with their analogues in the ring of polynomials, and the
33resulting expression is evaluated, resulting in a polynomial or a list
34of polynomials in internal form. A similar operation in another
35computer algebra system could be called 'expand' or so."
36 (labels ((p-eval (p) (poly-eval p vars order coefficient-class))
37 (p-eval-list (plist) (mapcar #'p-eval plist)))
38 (cond
39 ((eq expr 0)
40 (make-instance 'poly))
41 ((member expr vars :test #'equalp)
42 (let ((pos (position expr vars :test #'equalp)))
43 (make-poly-variable (length vars) pos)))
44 ((numberp expr)
45 (make-poly-constant (length vars) (make-instance coefficient-class :value expr)))
46 ((eq (car expr) +list-marker+)
47 (cons +list-marker+ (p-eval-list (cdr expr))))
48 (t
49 (case (car expr)
50 (+ (reduce #'add (p-eval-list (cdr expr))))
51 (- (apply #'subtract (p-eval-list (cdr expr))))
52 (*
53 (if (endp (cddr expr)) ;unary
54 (p-eval (cadr expr))
55 (apply #'multiply (p-eval-list (cdr expr)))))
56 (/
57 ;; A polynomial can be divided by a scalar
58 (cond
59 ((endp (cddr expr))
60 ;; A special case (/ ?), the inverse
61 (divide (cadr expr)))
62 (t
63 (let ((num (p-eval (cadr expr)))
64 (denom-inverse (apply #'divide (mapcar #'p-eval (cddr expr)))))
65 (multiply denom-inverse num)))))
66 (expt
67 (cond
68 ((member (cadr expr) vars :test #'equalp)
69 ;;Special handling of (expt var pow)
70 (let ((pos (position (cadr expr) vars :test #'equalp)))
71 (make-poly-variable (length vars) pos (caddr expr))))
72 ((not (and (integerp (caddr expr)) (plusp (caddr expr))))
73 ;; Negative power means division in coefficient ring
74 ;; Non-integer power means non-polynomial coefficient
75 expr)
76 (t (universal-expt (p-eval (cadr expr)) (caddr expr)))))
77 (otherwise
78 (error "Cannot evaluate as polynomial: ~A" expr)))))))
Note: See TracBrowser for help on using the repository browser.