SICP 2.11

ややこしやぁ。

(define make-interval cons)
(define upper-bound car)
(define lower-bound cdr)
(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 (mul-interval-fixed x y)
  (let ((xu (upper-bound x))
        (xl (lower-bound x))
        (yu (upper-bound y))
        (yl (lower-bound y)))
    (cond ((and (negative? xu) (negative? yu))  ; xu, yu, xl, yl < 0
           (make-interval a b))
          ((and (negative? xu) (negative? yl))  ; xu, xl, yl < 0, yu >= 0
           (make-interval (* xu yu) (* xl yu)))
          ((negative? xu)                       ; xu, xl < 0, yu, yl >= 0
           (make-interval (* xl yu) (* xu yl)))
          ((and (negative? xl) (negative? yu))  ; xl, yu, yl < 0, xu >= 0
           (make-interval (* xu yl) (* xl yl)))
          ((and (negative? xl) (negative? yl))  ; xl, yl <0, xu, yu >= 0
           (make-interval (min (* xu yl) (* xl yu))
                          (max (* xu yl) (* xl yu))))
          ((negative? yu)                       ; yu, yl <0, xu, xl >= 0
           (make-interval (* xu yu) (* xl yl)))
          ((negative? yl)                       ; yl < 0, xu, xl, yu >= 0
           (make-interval (* xu yl) (* xu yu)))
          (else                                 ; xu, xl, yu, yl >= 0
           (make-interval (* xl yl) (* xu yu))))))