#lang sicp
(define (make-interval a b) (cons a b))
(define (lower-bound int) (car int))
(define (upper-bound int) (cdr int))
(define (center i) (/ (+ (lower-bound i) (upper-bound i)) 2))
(define (width i) (/ (- (upper-bound i) (lower-bound i)) 2))
(define (percent i) (/ (width i) (center i)))
(define (make-percent-center x p)
    (make-interval (- x (* x p)) (+ x (* x p))))

(define (mul-interval x y)
  (let ((p1 (* (lower-bound x) (lower-bound y))) 
        (p2 (* (lower-bound x) (upper-bound y)))
        (p3 (* (upper-bound x) (lower-bound y))) 
        (p4 (* (upper-bound x) (upper-bound y))))
    (make-interval (min p1 p2 p3 p4) (max p1 p2 p3 p4))))

(define (contains? interval x)
  (and (<= (lower-bound interval) x) (<= x (upper-bound interval))))
(define (div-interval x y)
  (if (not (contains? y 0))
      (mul-interval x (make-interval (/ 1.0 (upper-bound y))
                                     (/ 1.0 (lower-bound y))))
      (error "div-interval called with interval containing zero")))
;; (define (disp-interval int)
;;   (display "[") (display (lower-bound int)) (display ", ") 
;;   (display (upper-bound int)) (display "]"))
(define (disp-interval int)
  (display (center int)) (display "(1 ± ") (display (percent int)) 
  (display ")"))
(define (disp-interval-op i1 i2 func character)
    (disp-interval i1) (display character) (disp-interval i2) (display " = ")
    (disp-interval (func i1 i2)) (newline))

;; (A+eps dA)/(B+eps dB) = ((A + eps dA)/B)/(1+eps dB/B)
;; =((A/B + eps dA/B) (1- eps dB/B)
;; =A/B + eps (dA/B - A/B dB/B)
;; =A/B(1+eps(dA/A - dB/B))
;; So the percent uncertainties add.
(let ((A (make-percent-center 1.0 0.05))
      (B (make-percent-center 10.0 0.1)))
  (display "Division of A/A:") (newline)
  (disp-interval-op A A div-interval " / ")

  (display "Division of A/B:") (newline)
  (disp-interval-op A B div-interval " / "))
