summaryrefslogtreecommitdiff
path: root/shared/intervals.rkt
blob: 270be51b27872e8e69c050a1b0ae77798af85b7c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#lang racket
(provide
  width
  make-center-width
  center
  make-center-percent
  percent
  pos?
  neg?
  mul-interval
  div-interval
  sub-interval
  add-interval
  make-interval
  upper-bound
  lower-bound
  print-interval)
(define (width x)
  (/ (- (upper-bound x) (lower-bound x)) 2))
(define (make-center-width c w)
  (make-interval (- c w) (+ c w)))
(define (center i)
  (/ (+ (lower-bound i) (upper-bound i)) 2))
(define (make-center-percent c p)
  (let ((toler (* c (/ p 100.0)))) 
    ((lambda (a b) 
       (if (> a b) 
         (make-interval b a)
         (make-interval a b)))
     (- c toler) 
     (+ c toler))))
(define (percent i)
  (let ((w (width i))
        (c (center i)))
    ;; (newline) (print c)(println w)
    ;; not defined: percent of interval centered at zero
    (if
      (<= c 0)
      0
      (abs (* 100 (/ w c))))))
(define (pos? x)
  (> x 0))
(define (neg? x)
  (< x 0))
(define (mul-interval x y)
  (cond
    ;; 1. all positive
    ((and
       (pos? (lower-bound x))
       (pos? (lower-bound y))
       (pos? (upper-bound x))
       (pos? (upper-bound y)))
     (make-interval (* (lower-bound x) (lower-bound y))
                    (* (upper-bound x) (upper-bound y))))
    ;; 2. one lower-bound neg
    ((and
       (neg? (lower-bound x))
       (pos? (lower-bound y))
       (pos? (upper-bound x))
       (pos? (upper-bound y)))
     (make-interval (* (lower-bound x) (upper-bound y))
                    (* (upper-bound x) (upper-bound y))))
    ;; 3. one lower-bound neg
    ((and
       (pos? (lower-bound x))
       (neg? (lower-bound y))
       (pos? (upper-bound x))
       (pos? (upper-bound y)))
     (make-interval (* (upper-bound x) (lower-bound y))
                    (* (upper-bound x) (upper-bound y))))
    ;; 4. one interval neg
    ((and
       (neg? (lower-bound x))
       (pos? (lower-bound y))
       (neg? (upper-bound x))
       (pos? (upper-bound y)))
     (make-interval (* (upper-bound x) (upper-bound y))
                    (* (lower-bound x) (lower-bound y))))
    ;; 5. one interval neg
    ((and
       (pos? (lower-bound x))
       (neg? (lower-bound y))
       (pos? (upper-bound x))
       (neg? (upper-bound y)))
     (make-interval (* (upper-bound x) (upper-bound y))
                    (* (lower-bound x) (lower-bound y))))
    ;; 6. one interval neg, one interval crossing zero
    ((and
       (neg? (lower-bound x))
       (neg? (lower-bound y))
       (neg? (upper-bound x))
       (pos? (upper-bound y)))
     (make-interval (* (upper-bound x) (upper-bound y))
                    (* (upper-bound x) (lower-bound y))))
    ;; 7. one interval neg, one interval crossing zero
    ((and
       (neg? (lower-bound x))
       (neg? (lower-bound y))
       (pos? (upper-bound x))
       (neg? (upper-bound y)))
     (make-interval (* (upper-bound x) (upper-bound y))
                    (* (upper-bound x) (lower-bound y))))
    ;; 8. all neg
    ((and
       (neg? (lower-bound x))
       (neg? (lower-bound y))
       (neg? (upper-bound x))
       (neg? (upper-bound y)))
     (make-interval (* (lower-bound x) (lower-bound y))
                    (* (upper-bound x) (upper-bound y))))
    ;; 9. both crossing zero
    ((and
       (neg? (lower-bound x))
       (neg? (lower-bound y))
       (pos? (upper-bound x))
       (pos? (upper-bound y)))
     (make-interval ((lambda (a b) (if (< a b) a b))
                     (* (lower-bound x) (upper-bound y))
                     (* (upper-bound x) (lower-bound y)))
                    ((lambda (a b) (if (> a b) a b))
                     (* (upper-bound x) (upper-bound y))
                     (* (lower-bound x) (lower-bound y)))))
    ;; 10. The case where one of the endpoints is neither negative or positive, 0
    (else (mul-interval-min-max x y))))
(define (mul-interval-min-max 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 (div-interval x y)
  (if (and (< 0 (lower-bound y)) (> 0 (upper-bound y)))
    (error "Division by interval spanning zero")
    (mul-interval 
      x
      (make-interval 
        (/ 1.0 (upper-bound y))
        (/ 1.0 (lower-bound y))))))
(define (sub-interval x y)
  (make-interval (- (lower-bound x) (upper-bound y))
                 (- (upper-bound x) (lower-bound y))))
(define (add-interval x y)
  (make-interval (+ (lower-bound x) (lower-bound y))
                 (+ (upper-bound x) (upper-bound y))))
(define (make-interval a b) (cons a b))
(define (lower-bound x) (car x))
(define (upper-bound x) (cdr x))
(define (print-interval x)
  (newline)
  (display "interval{")
  (display (lower-bound x))
  (display ",")
  (display (upper-bound x))
  (display "}")
  (newline))