Skip to content

2.11

; In passing, Ben also cryptically comments: “By testing the 
; signs of the endpoints of the intervals, it is possible to 
; break mul-interval into nine cases, only one of which 
; requires more than two multiplications.” Rewrite this procedure 
; using Ben’s suggestion

; Answer
; ------------------------------------
; The nine cases are based on 3 signs of x and y
; x can have [-ve, -ve], [-ve, +ve] and [+ve, +ve] (3)
;  (Note: [+ve, -ve] is NOT possible since order is always [lower, upper])
; y can have [-ve, -ve], [-ve, +ve] and [+ve, +ve] (3)
; Hence there can be 3x3 = 9 possibilities.

; Let's associate a value to each combination
; [-ve, -ve] => -1, [-ve, +ve] => 0, [+ve, +ve] => 1
; and define a function that returns us this value
(define (get-pair-value low up)
    (cond ((and (< low 0) (< up 0)) -1)
          ((and (< low 0) (> up 0)) 0)
          (else 1)))

; We can modify our `make-interval` to make sure always (a, b) has
; the property a < b
(define (make-interval a b)
    (cons (min a b) (max a b)))
(define (lower-bound z) (car z))
(define (upper-bound z) (cdr z))
(define (print-interval z)
    (newline)
    (display "[")
    (display (lower-bound z))
    (display ", ")
    (display (upper-bound z))
    (display "]"))

; Let's rewrite our `mul-interval` procedure
(define (mul-interval x y)
    (define xlow (lower-bound x))
    (define xup  (upper-bound x))
    (define ylow (lower-bound y))
    (define yup  (upper-bound y))

    (define xval (get-pair-value xlow xup))
    (define yval (get-pair-value ylow yup))

    (cond ((= xval -1)
           (cond ((= yval -1)            ; [-ve, -ve], [-ve, -ve]
                  (make-interval (* xup yup) (* xlow ylow)))
                 ((= yval 0)             ; [-ve, -ve], [-ve, +ve]
                  (make-interval (* xlow yup) (* xlow ylow)))
                 (else                   ; [-ve, -ve], [+ve, +ve]
                  (make-interval (* xlow yup) (* xup ylow)))))
          ((= xval 0)
           (cond ((= yval -1)            ; [-ve, +ve], [-ve, -ve]
                  (make-interval (* xup ylow) (* xlow ylow)))
                 ((= yval 0)             ; [-ve, +ve], [-ve, +ve]
                  (make-interval 
                    (min (* xlow yup)  (* xup ylow)) 
                    (max (* xlow ylow) (* xup yup))))
                 (else                   ; [-ve, +ve], [+ve, +ve]
                  (make-interval (* xlow yup) (* xup yup)))))
          (else
           (cond ((= yval -1)            ; [+ve, +ve], [-ve, -ve]
                  (make-interval (* xup ylow) (* xlow yup)))
                 ((= yval 0)             ; [+ve, +ve], [-ve, +ve]
                  (make-interval (* xup ylow) (* xup yup)))
                 (else                   ; [+ve, +ve], [+ve, +ve]
                  (make-interval (* xlow ylow) (* xup yup)))))))

; Testing
(print-interval (mul-interval 
    (make-interval -1.5 -1.2) 
    (make-interval -1   2))) ; [-3., 1.5]

(print-interval (mul-interval 
    (make-interval -5 3) 
    (make-interval -2 4)))   ; [-20, 12]