(define (nm1? n)
  (and (integer? n) (not (= n -1))))

(define (=expr? u v)
  (equal? (algebra-3 u) (algebra-3 v)))

(define (derivative u x)
  (derivatives `(d/d ,u ,x)))

(define (constant)
  (generate-uninterned-symbol 'C))

(define (integral u x)
  (integrals `(int ,u ,x)))


(define integrals
  (rule-solver
   (list
        
    (rule (int 0 (? x))
	  none
	  (? (constant)))

    (rule (int (? k) (? x))
	  (not (recursive-member? x k))
	  (+ (* (? k) (? x))
	     (? (constant))))

    (rule (int (+ (? u) (? v)) (? x))
	  none
	  (+ (+ (int (? u) (? x))
		(int (? v) (? x)))
	     (? (constant))))

    (rule (int (+ (* (? du/dx) (? v))
		  (* (? u) (? dv/dx))
	       (? x)))
	  (and (=expr? (derivative u x)
		       du/dx)
	       (=expr? (derivative v x)
		       dv/dx))
	  (+ (* (? u) (? v))
	     (? (constant))))

    (rule (int (/ (- (* (? du/dx) (? v))
		     (* (? u) (? dv/dx)))
		  (expt (? v) 2)))
	  (and (=expr? (derivative u x)
		       du/dx)
	       (=expr? (derivative v x)
		       dv/dx))
	  (+ (/ (? u) (? v))
	     (? (constant))))
    
    (rule (int (* (expt (? u) (? n nm1?))
		  (? du/dx)))
	  (=expr? (derivative u x) du/dx)
	  (+ (/ (expt (? u) (? (+ n 1)))
		(? (+ n 1)))
	     (? (constant))))
    )
   (lambda (expr)
     (not
      (recursive-member? 'int expr)))
   ))

#|

(pp (integral 'c 'x))
(+ (* c x) c4)

(pp (integral '(* b x) 'x))
#f			     ;sigh...

;;; No integral of a simple product...
;;; But this is a special case:

    (rule (int (* (? k) (? du/dx)) (? x))
	  (not (recursive-member? x k))
	  (+ (* (? k)
		(? (integral du/dx x)))
	     (? (constant))))

;;; But!

(pp (integral '(* b x) 'x))
#f

;;; Need the integral of x*dx

    (rule (int (? x) (? x))
	  none
	  (+ (/ (expt (? x) 2) 2)
	     (? (constant))))

(pp (integral '(* b x) 'x))
(+ (* b (+ (/ (expt x 2) 2) c13)) c12)

(pp
 (integral '(+ (* a (expt x 2)) (+ (* b x) c))
	   'x))
#f

;;; Need integral of x^n*dx

    (rule (int (expt (? x) (? n nm1?)) (? x))
	  none
	  (+ (/ (expt (? x) (? (+ n 1)))
		(? (+ n 1)))
	     (? (constant))))

(pp
 (integral '(+ (* a (expt x 2)) (+ (* b x) c))
	   'x))
(+
 (+ (+ (* a (+ (/ (expt x 3) 3) c39)) c38)
    (+ (+ (+ (* b (+ (/ (expt x 2) 2) c42))
	     c41)
	  (+ (* c x) c44))
       c35))
 c31)

;;; Ugh... Need all of algebra...

(pp
 (algebra-3
  (integral
   '(+ (* a (expt x 2)) (+ (* b x) c))
   'x)))
(+ c347
   c351
   c354
   c357
   c360
   (* a c355)
   (* a (/ (expt x 3) 3))
   (* b c358)
   (* b (/ (expt x 2) 2))
   (* c x))

;;; Still pretty crappy.
|#

(define integrals
  (rule-solver
   (list
        
    (rule (int 0 (? x))
	  none
	  (? (constant)))

    (rule (int (? k) (? x))
	  (not (recursive-member? x k))
	  (+ (* (? k) (? x))
	     (? (constant))))
      
    (rule (int (* (? k) (? du/dx)) (? x))
	  (and (not (recursive-member? x k))
	       (integral du/dx x))
	  (+ (* (? k) (? (integral du/dx x)))
	     (? (constant))))

    (rule (int (+ (? u) (? v)) (? x))
	  none
	  (+ (+ (int (? u) (? x))
		(int (? v) (? x)))
	     (? (constant))))

    (rule (int (+ (* (? du/dx) (? v))
		  (* (? u) (? dv/dx))
	       (? x)))
	  (and (=expr? (derivative u x)
		       du/dx)
	       (=expr? (derivative v x)
		       dv/dx))
	  (+ (* (? u) (? v))
	     (? (constant))))

    (rule (int (/ (- (* (? du/dx) (? v))
		     (* (? u) (? dv/dx)))
		  (expt (? v) 2)))
	  (and (=expr? (derivative u x)
		       du/dx)
	       (=expr? (derivative v x)
		       dv/dx))
	  (+ (/ (? u) (? v))
	     (? (constant))))

    (rule (int (? x) (? x))
	  none
	  (+ (/ (expt (? x) 2) 2)
	     (? (constant))))

    (rule (int (expt (? x) (? n nm1?)) (? x))
	  none
	  (+ (/ (expt (? x) (? (+ n 1)))
		(? (+ n 1)))
	     (? (constant))))

    (rule (int (* (expt (? u) (? n nm1?))
		  (? du/dx))
	       (? x))
	  (=expr? (derivative u x) du/dx)
	  (+ (/ (expt (? u) (? (+ n 1)))
		(? (+ n 1)))
	     (? (constant))))
    )
   (lambda (expr)
     (not
      (recursive-member? 'int expr)))
   ))


#|
;;; More rules
    
    (rule (int (* (/ 1 (? u)) (d/d (? u) (? x))) (? x))
	  none
	  (+ (log (? u)) (? (constant))))

    (rule (int (+ (? u) (? v)) (? x))
	  none
	  (+ (+ (int (? u) (? x)) (int (? v) (? x))) (? (constant))))

    (rule (int (* (exp (? u)) (d/d (? u) (? x))) (? x))
	  none
	  (+ (exp (? u)) (? (constant))))

    (rule (int (* (expt (? a) (? u)) (d/d (? u) (? x))) (? x))
	  none
	  (+ (/ (expt (? a) (? u)) (log (? a))) (? (constant))))

    (rule (int (* (sin (? u)) (d/d (? u) (? x))) (? x))
	  none
	  (+ (- (cos (? u))) (? (constant))))

    (rule (int (* (cos (? u)) (d/d (? u) (? x))) (? x))
	  none
	  (+ (sin (? u)) (? (constant))))

    (rule (int (* (? u) (* (d/d (? v) (? x)))) (? x))
	  none
	  (- (* (? u) (? v))
	     (int (* (? v) (* (d/d (? u) (? x)))) (? x))))
|#