Skip to content

Commit 652605d

Browse files
committed
Update Tests and README
1 parent 3233a5b commit 652605d

File tree

9 files changed

+805
-222
lines changed

9 files changed

+805
-222
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
.vscode/
2+
src/transform/storage/
23
Manifest.toml

LICENSE renamed to LICENSE.md

File renamed without changes.

README.md

+16-8
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
11
# SourceCodeMcCormick.jl
22

3-
This package is an experimental approach to use source-code transformation to apply McCormick relaxations
4-
to symbolic functions for use in deterministic global optimization. While packages like `McCormick.jl` [1]
5-
take set-valued McCormick objects and utilize McCormick relaxation rules to overload standard math operations,
6-
`SourceCodeMcCormick.jl` (SCMC) aims to interpret symbolic expressions, apply generalized McCormick rules,
7-
create source code that computes the McCormick relaxations and natural interval extension of the input,
8-
and compile the source code into functions that return pointwise values of the natural interval extension
9-
and convex/concave relaxations. This functionality is designed to be used for both algebraic and dynamic
10-
(in development) systems.
3+
| **PSOR Lab** | **Build Status** |
4+
|:------------:|:-----------------------------------------------------------------------------------------------:|
5+
| [![](https://img.shields.io/badge/Developed_by-PSOR_Lab-342674)](https://psor.uconn.edu/) | [![Build Status](https://github.com/PSORLab/SourceCodeMcCormick.jl/workflows/CI/badge.svg?branch=master)](https://github.com/PSORLab/SourceCodeMcCormick.jl/actions?query=workflow%3ACI) [![codecov](https://codecov.io/gh/PSORLab/SourceCodeMcCormick.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/PSORLab/SourceCodeMcCormick.jl)|
6+
7+
8+
This package uses source-code transformation to construct McCormick-based relaxations. Expressions composed
9+
of `Symbolics.jl`-type variables can be passed into `SourceCodeMcCormick.jl` (`SCMC`) functions, after which
10+
the expressions are factored, generalized McCormick relaxation rules and inclusion monotonic interval
11+
extensions are applied to the factors, and the factors are recombined symbolically to create expressions
12+
representing convex and concave relaxations and inclusion monotonic interval extensions of the original
13+
expression. The new expressions are compiled into functions that return pointwise values of these
14+
four elements, which can be used in, e.g., a branch-and-bound routine. These functions can be used with
15+
floating-point values, vectors of floating-point values, or CUDA arrays of floating point values (using
16+
`CUDA.jl`) to return outputs of the same type.
17+
18+
1119

1220
## Algebraic Systems
1321

test/addition.jl

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
@testset "Addition" begin
3+
@variables x, y
4+
5+
to_compute = y+5
6+
posreal_add_cv, posreal_add_cc, posreal_add_lo, posreal_add_hi, posreal_order = all_evaluators(to_compute)
7+
8+
to_compute = y-5
9+
negreal_add_cv, negreal_add_cc, negreal_add_lo, negreal_add_hi, negreal_order = all_evaluators(to_compute)
10+
11+
to_compute = x+y
12+
add_cv, add_cc, add_lo, add_hi, add_order = all_evaluators(to_compute)
13+
14+
# Addition rules are very simple; each component of the McCormick expansion
15+
# is added separately. No need to test more than one type of McCormick object
16+
# from McCormick.jl
17+
y_1D = MC{1,NS}(1.0, 2.0, Interval(0.0, 3.0), SVector{1, Float64}(0.5), SVector{1,Float64}(2.5), false)
18+
19+
xMC = 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)
20+
yMC = 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)
21+
22+
@test abs(eval_check(posreal_add_cv, y_1D) - (y_1D+5).cv) <= 1E-15
23+
@test abs(eval_check(posreal_add_cc, y_1D) - (y_1D+5).cc) <= 1E-15
24+
@test abs(eval_check(posreal_add_lo, y_1D) - (y_1D+5).Intv.lo) <= 1E-15
25+
@test abs(eval_check(posreal_add_hi, y_1D) - (y_1D+5).Intv.hi) <= 1E-15
26+
27+
@test abs(eval_check(negreal_add_cv, y_1D) - (y_1D-5).cv) <= 1E-15
28+
@test abs(eval_check(negreal_add_cc, y_1D) - (y_1D-5).cc) <= 1E-15
29+
@test abs(eval_check(negreal_add_lo, y_1D) - (y_1D-5).Intv.lo) <= 1E-15
30+
@test abs(eval_check(negreal_add_hi, y_1D) - (y_1D-5).Intv.hi) <= 1E-15
31+
32+
@test abs(eval_check(add_cv, xMC, yMC) - (xMC+yMC).cv) <= 1E-15
33+
@test abs(eval_check(add_cc, xMC, yMC) - (xMC+yMC).cc) <= 1E-15
34+
@test abs(eval_check(add_lo, xMC, yMC) - (xMC+yMC).Intv.lo) <= 1E-15
35+
@test abs(eval_check(add_hi, xMC, yMC) - (xMC+yMC).Intv.hi) <= 1E-15
36+
end

test/division.jl

+324
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,324 @@
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

Comments
 (0)