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