derive2.lisp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. ;;;; derive2.lisp
  2. ;;;;
  3. ;;;; Copyright (c) 2015 Samuel W. Flint <swflint@flintfam.org>
  4. (defpackage #:derive2
  5. (:use #:cl)
  6. (:export :derive
  7. :csc
  8. :sec))
  9. (in-package #:derive2)
  10. ;;; "derive2" goes here.
  11. (defvar *rules* '())
  12. (defun generate-match-expression (on arity &optional (type '=))
  13. (declare (symbol on type)
  14. (integer arity))
  15. (case type
  16. (=
  17. `(and (eq function ',on)
  18. (= arg-count ,arity)))
  19. (>
  20. `(and (eq function ',on)
  21. (> arg-count ,arity)))
  22. (>=
  23. `(and (eq function ',on)
  24. (>= arg-count ,arity)))))
  25. (defmacro def-expansion (name (on arity &optional type) (&rest arguments) &body expansion)
  26. (declare (ignorable name on arity type arguments expansion))
  27. (let ((match-expression (if type
  28. (generate-match-expression on arity type)
  29. (generate-match-expression on arity))))
  30. `(progn
  31. (push (list ',name
  32. (lambda (function &rest arguments &aux (arg-count (length arguments)))
  33. ,match-expression)
  34. (lambda (,@arguments)
  35. ,@expansion))
  36. *rules*)
  37. ',name)))
  38. (defun derive (function)
  39. (declare (cons function))
  40. (let ((op (first function)))
  41. (cond
  42. ((numberp op)
  43. 0)
  44. ((and (symbolp op)
  45. (= 1 (length function)))
  46. 1)
  47. (t
  48. (let ((expansion-function))
  49. (loop for (name test expander) in *rules*
  50. do (if (apply test function)
  51. (setf expansion-function expander)))
  52. (if (functionp expansion-function)
  53. (apply expansion-function (rest function))
  54. (error "Undefined expansion: ~a" op)))))))
  55. (defun csc (x)
  56. "csc -- (csc x)
  57. Calculate the cosecant of x"
  58. (/ (sin x)))
  59. (defun sec (x)
  60. "sec -- (sec x)
  61. Calculate the secant of x"
  62. (/ (cos x)))
  63. (def-expansion mult/2 (* 2) (first second)
  64. (cond
  65. ((numberp first)
  66. `(* ,first ,(derive (if (listp second) second (list second)))))
  67. ((numberp second)
  68. `(* ,second ,(derive (if (listp first) first (list second)))))
  69. (t
  70. `(+ (* ,first ,(derive (if (listp second) second (list second))))
  71. (* ,second ,(derive (if (listp first) first (list first))))))))
  72. (def-expansion exp/1 (exp 1) (expression)
  73. (if (listp expression)
  74. `(* (expt ,expression) ,(derive expression))
  75. (if (numberp expression)
  76. 0
  77. `(expt ,expression))))
  78. (def-expansion expt/2 (expt 2) (base exponent)
  79. (if (listp base)
  80. `(* ,exponent (expt ,base (1- ,exponent)) ,(derive base))
  81. `(* ,exponent (expt ,base (1- ,exponent)))))
  82. (def-expansion log/1 (log 1) (expression)
  83. `(/ ,(derive (if (listp expression) expression (list expression))) ,expression))
  84. (def-expansion log/2 (log 2) (number base))
  85. ;;; End derive2