123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- ;;;; derive2.lisp
- ;;;;
- ;;;; Copyright (c) 2015 Samuel W. Flint <swflint@flintfam.org>
- (defpackage #:derive2
- (:use #:cl)
- (:export :derive
- :csc
- :sec))
- (in-package #:derive2)
- ;;; "derive2" goes here.
- (defvar *rules* '())
- (defun generate-match-expression (on arity &optional (type '=))
- (declare (symbol on type)
- (integer arity))
- (case type
- (=
- `(and (eq function ',on)
- (= arg-count ,arity)))
- (>
- `(and (eq function ',on)
- (> arg-count ,arity)))
- (>=
- `(and (eq function ',on)
- (>= arg-count ,arity)))))
- (defmacro def-expansion (name (on arity &optional type) (&rest arguments) &body expansion)
- (declare (ignorable name on arity type arguments expansion))
- (let ((match-expression (if type
- (generate-match-expression on arity type)
- (generate-match-expression on arity))))
- `(progn
- (push (list ',name
- (lambda (function &rest arguments &aux (arg-count (length arguments)))
- ,match-expression)
- (lambda (,@arguments)
- ,@expansion))
- *rules*)
- ',name)))
- (defun derive (function)
- (declare (cons function))
- (let ((op (first function)))
- (cond
- ((numberp op)
- 0)
- ((and (symbolp op)
- (= 1 (length function)))
- 1)
- (t
- (let ((expansion-function))
- (loop for (name test expander) in *rules*
- do (if (apply test function)
- (setf expansion-function expander)))
- (if (functionp expansion-function)
- (apply expansion-function (rest function))
- (error "Undefined expansion: ~a" op)))))))
- (defun csc (x)
- "csc -- (csc x)
- Calculate the cosecant of x"
- (/ (sin x)))
- (defun sec (x)
- "sec -- (sec x)
- Calculate the secant of x"
- (/ (cos x)))
- (def-expansion mult/2 (* 2) (first second)
- (cond
- ((numberp first)
- `(* ,first ,(derive (if (listp second) second (list second)))))
- ((numberp second)
- `(* ,second ,(derive (if (listp first) first (list second)))))
- (t
- `(+ (* ,first ,(derive (if (listp second) second (list second))))
- (* ,second ,(derive (if (listp first) first (list first))))))))
- (def-expansion exp/1 (exp 1) (expression)
- (if (listp expression)
- `(* (expt ,expression) ,(derive expression))
- (if (numberp expression)
- 0
- `(expt ,expression))))
- (def-expansion expt/2 (expt 2) (base exponent)
- (if (listp base)
- `(* ,exponent (expt ,base (1- ,exponent)) ,(derive base))
- `(* ,exponent (expt ,base (1- ,exponent)))))
- (def-expansion log/1 (log 1) (expression)
- `(/ ,(derive (if (listp expression) expression (list expression))) ,expression))
- (def-expansion log/2 (log 2) (number base))
- ;;; End derive2
|