1
+ mid_expr (x, y, z) = IfElse. ifelse (x >= y, IfElse. ifelse (y >= z, y, IfElse. ifelse (y == x, y, IfElse. ifelse (z >= x, x, z))),
2
+ IfElse. ifelse (z >= y, y, IfElse. ifelse (x >= z, x, z)))
3
+
4
+ function div_cv_case (xcv, xcc, xL, xU, ycv, ycc, yL, yU)
5
+ yL_inv = inv (yU)
6
+ yU_inv = inv (yL)
7
+ ycv_inv = ifelse (yL > 0.0 , ifelse (yU <= ycv, 1.0 ./ ycv,
8
+ ifelse (yU >= ycc, 1.0 ./ ycc, 1.0 ./ yU)),
9
+ ifelse (yU < 0.0 , ifelse (yL == yU, mid_expr (ycc, ycv, yL).^ (- 1 ),
10
+ ((yL.^ (- 1 ))* (yU - mid_expr (ycc, ycv, yL)) + (yU.^ (- 1 ))* (mid_expr (ycc, ycv, yL) - yL)). / (yU - yL)),
11
+ NaN ))
12
+ ycc_inv = ifelse (yL > 0.0 , ifelse (yL <= ycv, (yU + yL - ycv). / (yL* yU),
13
+ ifelse (yL >= ycc, (yU + yL - ycc). / (yL* yU), 1.0 ./ yL)),
14
+ ifelse (yU < 0.0 , mid_expr (ycc, ycv, yU).^ (- 1 ),
15
+ NaN ))
16
+ if xL >= 0.0
17
+ if yL >= 0.0
18
+ if yU_inv* xcv + xU* ycv_inv - xU* yU_inv > yL_inv* xcv + xL* ycv_inv - xL* yL_inv
19
+ return 1
20
+ else
21
+ return 2
22
+ end
23
+ elseif yU <= 0.0
24
+ if (- yU_inv)* xcc + xU* (- ycv_inv) - xU* (- yU_inv) > (- yL_inv)* xcc + xL* (- ycv_inv) - xL* (- yL_inv)
25
+ return 3
26
+ else
27
+ return 4
28
+ end
29
+ else
30
+ return 5
31
+ end
32
+ elseif xU <= 0.0
33
+ if yL >= 0.0
34
+ if yL_inv* (- xcv) + (- xL)* ycc_inv - (- xL)* yL_inv > yU_inv* (- xcv) + (- xU)* ycc_inv - (- xU)* yU_inv
35
+ return 6
36
+ else
37
+ return 7
38
+ end
39
+ elseif yU <= 0.0
40
+ if yL_inv* xcc + xL* ycc_inv - xL* yL_inv > yU_inv* xcc + xU* ycc_inv - xU* yU_inv
41
+ return 8
42
+ else
43
+ return 9
44
+ end
45
+ else
46
+ return 10
47
+ end
48
+ else
49
+ if yL >= 0.0
50
+ if xU* ycv_inv + yU_inv* xcv - yU_inv* xU > xL* ycc_inv + yL_inv* xcv - yL_inv* xL
51
+ return 11
52
+ else
53
+ return 12
54
+ end
55
+ elseif yU <= 0.0
56
+ if xL* (- ycc_inv) + (- yL_inv)* xcc - (- yL_inv)* xL > xU* (- ycv_inv) + (- yU_inv)* xcc - (- yU_inv)* xU
57
+ return 13
58
+ else
59
+ return 14
60
+ end
61
+ else
62
+ return 15
63
+ end
64
+ end
65
+ end
66
+ function div_cc_case (xcv, xcc, xL, xU, ycv, ycc, yL, yU)
67
+ yL_inv = inv (yU)
68
+ yU_inv = inv (yL)
69
+ ycv_inv = ifelse (yL > 0.0 , ifelse (yU <= ycv, 1.0 ./ ycv,
70
+ ifelse (yU >= ycc, 1.0 ./ ycc, 1.0 ./ yU)),
71
+ ifelse (yU < 0.0 , ifelse (yL == yU, mid_expr (ycc, ycv, yL).^ (- 1 ),
72
+ ((yL.^ (- 1 ))* (yU - mid_expr (ycc, ycv, yL)) + (yU.^ (- 1 ))* (mid_expr (ycc, ycv, yL) - yL)). / (yU - yL)),
73
+ NaN ))
74
+ ycc_inv = ifelse (yL > 0.0 , ifelse (yL <= ycv, (yU + yL - ycv). / (yL* yU),
75
+ ifelse (yL >= ycc, (yU + yL - ycc). / (yL* yU), 1.0 ./ yL)),
76
+ ifelse (yU < 0.0 , mid_expr (ycc, ycv, yU).^ (- 1 ),
77
+ NaN ))
78
+ if xL >= 0.0
79
+ if yL >= 0.0
80
+ if yL_inv* xcc + xU* ycc_inv - xU* yL_inv > yU_inv* xcc + xL* ycc_inv - xL* yU_inv
81
+ return 1
82
+ else
83
+ return 2
84
+ end
85
+ elseif yU <= 0.0
86
+ if (- yL_inv)* xcv + xU* (- ycc_inv) - xU* (- yL_inv) > (- yU_inv)* xcv + xL* (- ycc_inv) - xL* (- yU_inv)
87
+ return 3
88
+ else
89
+ return 4
90
+ end
91
+ else
92
+ return 5
93
+ end
94
+ elseif xU <= 0.0
95
+ if yL >= 0.0
96
+ if yU_inv* (- xcc) + (- xL)* ycv_inv - (- xL)* yU_inv > yL_inv* (- xcc) + (- xU)* ycv_inv - (- xU)* yL_inv
97
+ return 6
98
+ else
99
+ return 7
100
+ end
101
+ elseif yU <= 0.0
102
+ if yU_inv* xcv + xL* ycv_inv - xL* yU_inv > yL_inv* xcv + xU* ycv_inv - xU* yL_inv
103
+ return 8
104
+ else
105
+ return 9
106
+ end
107
+ else
108
+ return 10
109
+ end
110
+ else
111
+ if yL >= 0.0
112
+ if xL* ycv_inv + yU_inv* xcc - yU_inv* xL > xU* ycc_inv + yL_inv* xcc - yL_inv* xU
113
+ return 11
114
+ else
115
+ return 12
116
+ end
117
+ elseif yU <= 0.0
118
+ if xU* (- ycc_inv) + (- yL_inv)* xcv - (- yL_inv)* xU > xL* (- ycv_inv) + (- yU_inv)* xcv - (- yU_inv)* xL
119
+ return 13
120
+ else
121
+ return 14
122
+ end
123
+ else
124
+ return 15
125
+ end
126
+ end
127
+ end
128
+ div_cv_case (A:: MC , B:: MC ) = div_cv_case (A. cv, A. cc, A. Intv. lo, A. Intv. hi, B. cv, B. cc, B. Intv. lo, B. Intv. hi)
129
+ div_cc_case (A:: MC , B:: MC ) = div_cv_case (A. cv, A. cc, A. Intv. lo, A. Intv. hi, B. cv, B. cc, B. Intv. lo, B. Intv. hi)
130
+
131
+ # For division, need to test all cases with MC*MC, then several cases with Real types
132
+ @testset " Division" begin
133
+ @variables x, y
134
+
135
+ # Real divided by a McCormick object
136
+ pos = MC {1,NS} (1.0 , 1.5 , Interval (0.5 , 2.0 ), SVector {1, Float64} (1.0 ), SVector {1, Float64} (3.0 ), false )
137
+ mix = MC {1,NS} (- 0.5 , 0.5 , Interval (- 2.0 , 2.0 ), SVector {1, Float64} (- 0.5 ), SVector {1, Float64} (1.0 ), false )
138
+ neg = - pos
139
+
140
+ to_compute = 5.0 / y
141
+ posreal_div_cv, posreal_div_cc, posreal_div_lo, posreal_div_hi, posreal_order = all_evaluators (to_compute)
142
+
143
+ to_compute = - 5.0 / y
144
+ negreal_div_cv, negreal_div_cc, negreal_div_lo, negreal_div_hi, negreal_order = all_evaluators (to_compute)
145
+
146
+ # pos/pos
147
+ @test abs (eval_check (posreal_div_cv, pos) - (5.0 / pos). cv) <= 1E-15
148
+ @test abs (eval_check (posreal_div_cc, pos) - (5.0 / pos). cc) <= 1E-15
149
+ @test abs (eval_check (posreal_div_lo, pos) - (5.0 / pos). Intv. lo) <= 1E-15
150
+ @test abs (eval_check (posreal_div_hi, pos) - (5.0 / pos). Intv. hi) <= 1E-15
151
+
152
+ # pos/mix
153
+ @test isnan (eval_check (posreal_div_cv, mix))
154
+ @test isnan ((5.0 / mix). cv)
155
+ @test isnan (eval_check (posreal_div_cc, mix))
156
+ @test isnan ((5.0 / mix). cc)
157
+ @test isnan (eval_check (posreal_div_lo, mix))
158
+ @test isnan ((5.0 / mix). Intv. lo)
159
+ @test isnan (eval_check (posreal_div_hi, mix))
160
+ @test isnan ((5.0 / mix). Intv. hi)
161
+
162
+ # pos/neg
163
+ @test abs (eval_check (posreal_div_cv, neg) - (5.0 / neg). cv) <= 1E-15
164
+ @test abs (eval_check (posreal_div_cc, neg) - (5.0 / neg). cc) <= 1E-15
165
+ @test abs (eval_check (posreal_div_lo, neg) - (5.0 / neg). Intv. lo) <= 1E-15
166
+ @test abs (eval_check (posreal_div_hi, neg) - (5.0 / neg). Intv. hi) <= 1E-15
167
+
168
+ # neg/pos
169
+ @test abs (eval_check (negreal_div_cv, pos) - (- 5.0 / pos). cv) <= 1E-15
170
+ @test abs (eval_check (negreal_div_cc, pos) - (- 5.0 / pos). cc) <= 1E-15
171
+ @test abs (eval_check (negreal_div_lo, pos) - (- 5.0 / pos). Intv. lo) <= 1E-15
172
+ @test abs (eval_check (negreal_div_hi, pos) - (- 5.0 / pos). Intv. hi) <= 1E-15
173
+
174
+ # neg/mix
175
+ @test isnan (eval_check (negreal_div_cv, mix))
176
+ @test isnan ((- 5.0 / mix). cv)
177
+ @test isnan (eval_check (negreal_div_cc, mix))
178
+ @test isnan ((- 5.0 / mix). cc)
179
+ @test isnan (eval_check (negreal_div_lo, mix))
180
+ @test isnan ((- 5.0 / mix). Intv. lo)
181
+ @test isnan (eval_check (negreal_div_hi, mix))
182
+ @test isnan ((- 5.0 / mix). Intv. hi)
183
+
184
+ # neg/neg
185
+ @test abs (eval_check (negreal_div_cv, neg) - (- 5.0 / neg). cv) <= 1E-15
186
+ @test abs (eval_check (negreal_div_cc, neg) - (- 5.0 / neg). cc) <= 1E-15
187
+ @test abs (eval_check (negreal_div_lo, neg) - (- 5.0 / neg). Intv. lo) <= 1E-15
188
+ @test abs (eval_check (negreal_div_hi, neg) - (- 5.0 / neg). Intv. hi) <= 1E-15
189
+
190
+ # Note: McCormick object divided by a real automatically converts from (MC/real) to (MC*(real^-1))
191
+ # through Symbolics.jl, so this is simply multiplication.
192
+
193
+
194
+ # McCormick object divided by a McCormick object. Verify that cases are satisfied before
195
+ # checking the solution using the cv/cc case checker functions
196
+ pos = MC {2,NS} (1.0 , 1.5 , Interval (0.5 , 2.0 ), SVector {2, Float64} (1.0 , 2.0 ), SVector {2, Float64} (3.0 , 4.0 ), false )
197
+ pos_lo = MC {2,NS} (0.5 , 0.5 , Interval (0.5 , 2.0 ), SVector {2, Float64} (1.0 , 2.0 ), SVector {2, Float64} (3.0 , 4.0 ), false )
198
+ pos_hi = MC {2,NS} (1.8 , 1.9 , Interval (0.5 , 2.0 ), SVector {2, Float64} (1.0 , 2.0 ), SVector {2, Float64} (3.0 , 4.0 ), false )
199
+ mix = MC {2,NS} (- 0.5 , 0.5 , Interval (- 2.0 , 2.0 ), SVector {2, Float64} (- 0.5 , 0.5 ), SVector {2, Float64} (1.0 , - 1.0 ), false )
200
+ neg = - pos
201
+ neg_lo = - pos_lo
202
+ neg_hi = - pos_hi
203
+
204
+ @variables x, y
205
+ to_compute = x/ y
206
+ div_cv, div_cc, div_lo, div_hi, order = all_evaluators (to_compute)
207
+
208
+ @test div_cv_case (pos, pos_lo) == 1
209
+ @test div_cc_case (pos, pos_lo) == 1
210
+ @test abs (eval_check (div_cv, pos, pos_lo) - (pos/ pos_lo). cv) <= 1E-15
211
+ @test abs (eval_check (div_cc, pos, pos_lo) - (pos/ pos_lo). cc) <= 1E-15
212
+ @test abs (eval_check (div_lo, pos, pos_lo) - (pos/ pos_lo). Intv. lo) <= 1E-15
213
+ @test abs (eval_check (div_hi, pos, pos_lo) - (pos/ pos_lo). Intv. hi) <= 1E-15
214
+
215
+ @test div_cv_case (pos, pos_hi) == 2
216
+ @test div_cc_case (pos, pos_hi) == 2
217
+ @test abs (eval_check (div_cv, pos, pos_hi) - (pos/ pos_hi). cv) <= 1E-15
218
+ @test abs (eval_check (div_cc, pos, pos_hi) - (pos/ pos_hi). cc) <= 1E-15
219
+ @test abs (eval_check (div_lo, pos, pos_hi) - (pos/ pos_hi). Intv. lo) <= 1E-15
220
+ @test abs (eval_check (div_hi, pos, pos_hi) - (pos/ pos_hi). Intv. hi) <= 1E-15
221
+
222
+ @test div_cv_case (pos, neg_lo) == 3
223
+ @test div_cc_case (pos, neg_lo) == 3
224
+ @test abs (eval_check (div_cv, pos, neg_lo) - (pos/ neg_lo). cv) <= 1E-15
225
+ @test abs (eval_check (div_cc, pos, neg_lo) - (pos/ neg_lo). cc) <= 1E-15
226
+ @test abs (eval_check (div_lo, pos, neg_lo) - (pos/ neg_lo). Intv. lo) <= 1E-15
227
+ @test abs (eval_check (div_hi, pos, neg_lo) - (pos/ neg_lo). Intv. hi) <= 1E-15
228
+
229
+ @test div_cv_case (pos, neg) == 4
230
+ @test div_cc_case (pos, neg) == 4
231
+ @test abs (eval_check (div_cv, pos, neg) - (pos/ neg). cv) <= 1E-15
232
+ @test abs (eval_check (div_cc, pos, neg) - (pos/ neg). cc) <= 1E-15
233
+ @test abs (eval_check (div_lo, pos, neg) - (pos/ neg). Intv. lo) <= 1E-15
234
+ @test abs (eval_check (div_hi, pos, neg) - (pos/ neg). Intv. hi) <= 1E-15
235
+
236
+ @test div_cv_case (pos_hi, mix) == 5
237
+ @test div_cc_case (pos_hi, mix) == 5
238
+ @test isnan (eval_check (div_cv, pos_hi, mix))
239
+ @test isnan ((pos_hi/ mix). cv)
240
+ @test isnan (eval_check (div_cc, pos_hi, mix))
241
+ @test isnan ((pos_hi/ mix). cc)
242
+ @test isnan (eval_check (div_lo, pos_hi, mix))
243
+ @test isnan ((pos_hi/ mix). Intv. lo)
244
+ @test isnan (eval_check (div_hi, pos_hi, mix))
245
+ @test isnan ((pos_hi/ mix). Intv. hi)
246
+
247
+ @test div_cv_case (neg, pos_lo) == 6
248
+ @test div_cc_case (neg, pos_lo) == 6
249
+ @test abs (eval_check (div_cv, neg, pos_lo) - (neg/ pos_lo). cv) <= 1E-15
250
+ @test abs (eval_check (div_cc, neg, pos_lo) - (neg/ pos_lo). cc) <= 1E-15
251
+ @test abs (eval_check (div_lo, neg, pos_lo) - (neg/ pos_lo). Intv. lo) <= 1E-15
252
+ @test abs (eval_check (div_hi, neg, pos_lo) - (neg/ pos_lo). Intv. hi) <= 1E-15
253
+
254
+ @test div_cv_case (neg, pos_hi) == 7
255
+ @test div_cc_case (neg, pos_hi) == 7
256
+ @test abs (eval_check (div_cv, neg, pos_hi) - (neg/ pos_hi). cv) <= 1E-15
257
+ @test abs (eval_check (div_cc, neg, pos_hi) - (neg/ pos_hi). cc) <= 1E-15
258
+ @test abs (eval_check (div_lo, neg, pos_hi) - (neg/ pos_hi). Intv. lo) <= 1E-15
259
+ @test abs (eval_check (div_hi, neg, pos_hi) - (neg/ pos_hi). Intv. hi) <= 1E-15
260
+
261
+ @test div_cv_case (neg, neg_lo) == 8
262
+ @test div_cc_case (neg, neg_lo) == 8
263
+ @test abs (eval_check (div_cv, neg, neg_lo) - (neg/ neg_lo). cv) <= 1E-15
264
+ @test abs (eval_check (div_cc, neg, neg_lo) - (neg/ neg_lo). cc) <= 1E-15
265
+ @test abs (eval_check (div_lo, neg, neg_lo) - (neg/ neg_lo). Intv. lo) <= 1E-15
266
+ @test abs (eval_check (div_hi, neg, neg_lo) - (neg/ neg_lo). Intv. hi) <= 1E-15
267
+
268
+ @test div_cv_case (neg, neg_hi) == 9
269
+ @test div_cc_case (neg, neg_hi) == 9
270
+ @test abs (eval_check (div_cv, neg, neg_hi) - (neg/ neg_hi). cv) <= 1E-15
271
+ @test abs (eval_check (div_cc, neg, neg_hi) - (neg/ neg_hi). cc) <= 1E-15
272
+ @test abs (eval_check (div_lo, neg, neg_hi) - (neg/ neg_hi). Intv. lo) <= 1E-15
273
+ @test abs (eval_check (div_hi, neg, neg_hi) - (neg/ neg_hi). Intv. hi) <= 1E-15
274
+
275
+ @test div_cv_case (neg, mix) == 10
276
+ @test div_cc_case (neg, mix) == 10
277
+ @test isnan (eval_check (div_cv, neg, mix))
278
+ @test isnan ((neg/ mix). cv)
279
+ @test isnan (eval_check (div_cc, neg, mix))
280
+ @test isnan ((neg/ mix). cc)
281
+ @test isnan (eval_check (div_lo, neg, mix))
282
+ @test isnan ((neg/ mix). Intv. lo)
283
+ @test isnan (eval_check (div_hi, neg, mix))
284
+ @test isnan ((neg/ mix). Intv. hi)
285
+
286
+ @test div_cv_case (mix, pos_lo) == 11
287
+ @test div_cc_case (mix, pos_lo) == 11
288
+ @test abs (eval_check (div_cv, mix, pos_lo) - (mix/ pos_lo). cv) <= 1E-15
289
+ @test abs (eval_check (div_cc, mix, pos_lo) - (mix/ pos_lo). cc) <= 1E-15
290
+ @test abs (eval_check (div_lo, mix, pos_lo) - (mix/ pos_lo). Intv. lo) <= 1E-15
291
+ @test abs (eval_check (div_hi, mix, pos_lo) - (mix/ pos_lo). Intv. hi) <= 1E-15
292
+
293
+ @test div_cv_case (mix, pos) == 12
294
+ @test div_cc_case (mix, pos) == 12
295
+ @test abs (eval_check (div_cv, mix, pos) - (mix/ pos). cv) <= 1E-15
296
+ @test abs (eval_check (div_cc, mix, pos) - (mix/ pos). cc) <= 1E-15
297
+ @test abs (eval_check (div_lo, mix, pos) - (mix/ pos). Intv. lo) <= 1E-15
298
+ @test abs (eval_check (div_hi, mix, pos) - (mix/ pos). Intv. hi) <= 1E-15
299
+
300
+ @test div_cv_case (mix, neg) == 13
301
+ @test div_cc_case (mix, neg) == 13
302
+ @test abs (eval_check (div_cv, mix, neg) - (mix/ neg). cv) <= 1E-15
303
+ @test abs (eval_check (div_cc, mix, neg) - (mix/ neg). cc) <= 1E-15
304
+ @test abs (eval_check (div_lo, mix, neg) - (mix/ neg). Intv. lo) <= 1E-15
305
+ @test abs (eval_check (div_hi, mix, neg) - (mix/ neg). Intv. hi) <= 1E-15
306
+
307
+ @test div_cv_case (mix, neg_lo) == 14
308
+ @test div_cc_case (mix, neg_lo) == 14
309
+ @test abs (eval_check (div_cv, mix, neg_lo) - (mix/ neg_lo). cv) <= 1E-15
310
+ @test abs (eval_check (div_cc, mix, neg_lo) - (mix/ neg_lo). cc) <= 1E-15
311
+ @test abs (eval_check (div_lo, mix, neg_lo) - (mix/ neg_lo). Intv. lo) <= 1E-15
312
+ @test abs (eval_check (div_hi, mix, neg_lo) - (mix/ neg_lo). Intv. hi) <= 1E-15
313
+
314
+ @test div_cv_case (mix, mix) == 15
315
+ @test div_cc_case (mix, mix) == 15
316
+ @test isnan (eval_check (div_cv, mix, mix))
317
+ @test isnan ((mix/ mix). cv)
318
+ @test isnan (eval_check (div_cc, mix, mix))
319
+ @test isnan ((mix/ mix). cc)
320
+ @test isnan (eval_check (div_lo, mix, mix))
321
+ @test isnan ((mix/ mix). Intv. lo)
322
+ @test isnan (eval_check (div_hi, mix, mix))
323
+ @test isnan ((mix/ mix). Intv. hi)
324
+ end
0 commit comments