4242-type bool_result () :: 'true' | 'false' | 'maybe' .
4343-type op () :: atom ().
4444
45+ -import (lists , [foldl /3 ]).
46+
4547% % Maximum size of integers in bits to keep ranges for.
4648-define (NUM_BITS , 128 ).
4749
@@ -52,95 +54,51 @@ bounds('bnot', R0) ->
5254 R = {inf_add (inf_neg (B ), - 1 ), inf_add (inf_neg (A ), - 1 )},
5355 normalize (R );
5456bounds (abs , R ) ->
55- case R of
56- {A ,B } when is_integer (A ), is_integer (B ) ->
57- Min = 0 ,
58- Max = max (abs (A ), abs (B )),
59- {Min ,Max };
60- _ ->
61- {0 ,'+inf' }
62- end .
57+ [A ,B ] = canonical_arg (R ),
58+ AbsA = inf_abs (A ),
59+ AbsB = inf_abs (B ),
60+ Min = case {inf_sign (A ),inf_sign (B )} of
61+ {'-' ,'+' } -> 0 ;
62+ {_ ,_ } -> inf_min (AbsA , AbsB )
63+ end ,
64+ Max = inf_max (AbsA , AbsB ),
65+ normalize ({Min ,Max }).
6366
6467-spec bounds (op (), range (), range ()) -> range_result ().
6568
6669bounds ('+' , R1 , R2 ) ->
67- case {R1 ,R2 } of
68- {{A ,B }, {C ,D }} when abs (A ) bsr ? NUM_BITS =:= 0 ,
69- abs (B ) bsr ? NUM_BITS =:= 0 ,
70- abs (C ) bsr ? NUM_BITS =:= 0 ,
71- abs (D ) bsr ? NUM_BITS =:= 0 ->
72- normalize ({A + C ,B + D });
73- {{'-inf' ,B }, {_C ,D }} when abs (B ) bsr ? NUM_BITS =:= 0 ,
74- abs (D ) bsr ? NUM_BITS =:= 0 ->
75- normalize ({'-inf' ,B + D });
76- {{_A ,B }, {'-inf' ,D }} when abs (B ) bsr ? NUM_BITS =:= 0 ,
77- abs (D ) bsr ? NUM_BITS =:= 0 ->
78- normalize ({'-inf' ,B + D });
79- {{A ,'+inf' }, {C ,_D }} when abs (A ) bsr ? NUM_BITS =:= 0 ,
80- abs (C ) bsr ? NUM_BITS =:= 0 ->
81- normalize ({A + C ,'+inf' });
82- {{A ,_B }, {C ,'+inf' }} when abs (A ) bsr ? NUM_BITS =:= 0 ,
83- abs (C ) bsr ? NUM_BITS =:= 0 ->
84- normalize ({A + C ,'+inf' });
85- {_ , _ } ->
86- any
87- end ;
70+ [A ,B ,C ,D ] = canonical_args (R1 , R2 ),
71+ normalize ({inf_add (A , C ), inf_add (B , D )});
8872bounds ('-' , R1 , R2 ) ->
89- case { R1 ,R2 } of
90- {{ A ,B }, { C ,D }} when abs (A ) bsr ? NUM_BITS =:= 0 ,
91- abs (B ) bsr ? NUM_BITS =:= 0 ,
92- abs (C ) bsr ? NUM_BITS =:= 0 ,
93- abs (D ) bsr ? NUM_BITS =:= 0 ->
73+ case canonical_args ( R1 , R2 ) of
74+ [ A ,B , C ,D ] when is_integer (A ),
75+ is_integer (B ),
76+ is_integer (C ),
77+ is_integer (D ) ->
9478 normalize ({A - D ,B - C });
95- {{A ,'+inf' }, {_C ,D }} when abs (A ) bsr ? NUM_BITS =:= 0 ,
96- abs (D ) bsr ? NUM_BITS =:= 0 ->
79+ [A ,'+inf' ,_C ,D ] when is_integer (A ), is_integer (D ) ->
9780 normalize ({A - D ,'+inf' });
98- {{_A ,B }, {C ,'+inf' }} when abs (B ) bsr ? NUM_BITS =:= 0 ,
99- abs (C ) bsr ? NUM_BITS =:= 0 ->
81+ [_A ,B ,C ,'+inf' ] when is_integer (B ), is_integer (C ) ->
10082 normalize ({'-inf' ,B - C });
101- {{'-inf' ,B }, {C ,_D }} when abs (B ) bsr ? NUM_BITS =:= 0 ,
102- abs (C ) bsr ? NUM_BITS =:= 0 ->
83+ ['-inf' ,B ,C ,_D ] when is_integer (B ), is_integer (C ) ->
10384 normalize ({'-inf' ,B - C });
104- {{A ,_B }, {'-inf' ,D }} when abs (A ) bsr ? NUM_BITS =:= 0 ,
105- abs (D ) bsr ? NUM_BITS =:= 0 ->
85+ [A ,_B ,'-inf' ,D ] when is_integer (A ), is_integer (D ) ->
10686 normalize ({A - D ,'+inf' });
107- { _ , _ } ->
87+ [ _ , _ , _ , _ ] ->
10888 any
10989 end ;
11090bounds ('*' , R1 , R2 ) ->
111- case {R1 ,R2 } of
112- {{A ,B }, {C ,D }} when abs (A ) bsr ? NUM_BITS =:= 0 ,
113- abs (B ) bsr ? NUM_BITS =:= 0 ,
114- abs (C ) bsr ? NUM_BITS =:= 0 ,
115- abs (D ) bsr ? NUM_BITS =:= 0 ->
116- All = [X * Y || X <- [A ,B ], Y <- [C ,D ]],
117- Min = lists :min (All ),
118- Max = lists :max (All ),
119- normalize ({Min ,Max });
120- {{A ,'+inf' }, {C ,'+inf' }} when abs (A ) bsr ? NUM_BITS =:= 0 , A >= 0 ,
121- abs (C ) bsr ? NUM_BITS =:= 0 , C >= 0 ->
122- {A * C ,'+inf' };
123- {{A ,'+inf' }, {C ,D }} when abs (A ) bsr ? NUM_BITS =:= 0 ,
124- abs (C ) bsr ? NUM_BITS =:= 0 ,
125- abs (D ) bsr ? NUM_BITS =:= 0 ,
126- C >= 0 ->
127- {min (A * C , A * D ),'+inf' };
128- {{'-inf' ,B }, {C ,D }} when abs (B ) bsr ? NUM_BITS =:= 0 ,
129- abs (C ) bsr ? NUM_BITS =:= 0 ,
130- abs (D ) bsr ? NUM_BITS =:= 0 ,
131- C >= 0 ->
132- {'-inf' ,max (B * C , B * D )};
133- {{A ,B }, {'-inf' ,_ }} when is_integer (A ), is_integer (B ) ->
134- bounds ('*' , R2 , R1 );
135- {{A ,B }, {_ ,'+inf' }} when is_integer (A ), is_integer (B ) ->
136- bounds ('*' , R2 , R1 );
137- {_ , _ } ->
138- any
139- end ;
91+ [A ,B ,C ,D ] = canonical_args (R1 , R2 ),
92+ All = [inf_mul (X , Y ) || X <- [A ,B ], Y <- [C ,D ]],
93+ Min = foldl (fun inf_min /2 , '+inf' , All ),
94+ Max = foldl (fun inf_max /2 , '-inf' , All ),
95+ normalize ({Min ,Max });
14096bounds ('div' , R1 , R2 ) ->
141- div_bounds (R1 , R2 );
97+ [A ,B ,C ,D ] = canonical_args (R1 , R2 ),
98+ div_bounds ({A ,B }, {C ,D });
14299bounds ('rem' , R1 , R2 ) ->
143- rem_bounds (R1 , R2 );
100+ [A ,B ,C ,D ] = canonical_args (R1 , R2 ),
101+ rem_bounds ({A ,B }, {C ,D });
144102bounds ('band' , R1 , R2 ) ->
145103 [A ,B ,C ,D ] = canonical_args (R1 , R2 ),
146104 normalize (min_max_band (A , B , C , D ));
@@ -255,13 +213,15 @@ div_bounds({A,B}, {C,D}) when is_integer(A), is_integer(B),
255213 Min = lists :min (All ),
256214 Max = lists :max (All ),
257215 normalize ({Min ,Max });
258- div_bounds ({A ,'+inf' }, {C ,D }) when is_integer (C ), C > 0 , is_integer (D ) ->
259- Min = min (A div C , A div D ),
216+ div_bounds ({A ,'+inf' }, {C ,D }) when is_integer (A ),
217+ is_integer (C ), C > 0 ->
218+ Min = min (A div C , inf_div (A , D )),
260219 Max = '+inf' ,
261220 normalize ({Min ,Max });
262- div_bounds ({'-inf' ,B }, {C ,D }) when is_integer (C ), C > 0 , is_integer (D ) ->
221+ div_bounds ({'-inf' ,B }, {C ,D }) when is_integer (B ),
222+ is_integer (C ), C > 0 ->
263223 Min = '-inf' ,
264- Max = max (B div C , B div D ),
224+ Max = max (B div C , inf_div ( B , D ) ),
265225 normalize ({Min ,Max });
266226div_bounds ({A ,B }, _ ) when is_integer (A ), is_integer (B ) ->
267227 Max = max (abs (A ), abs (B )),
@@ -291,9 +251,7 @@ rem_bounds({A,B}, _) ->
291251 % % include zero.
292252 Min = inf_min (0 , A ),
293253 Max = inf_max (0 , B ),
294- normalize ({Min ,Max });
295- rem_bounds (_ , _ ) ->
296- any .
254+ normalize ({Min ,Max }).
297255
298256-if (false ).
299257min_max_band (A , B , C , D ) ->
@@ -737,8 +695,28 @@ inf_neg('-inf') -> '+inf';
737695inf_neg ('+inf' ) -> '-inf' ;
738696inf_neg (N ) -> - N .
739697
740- inf_add (Int , N ) when is_integer (Int ) -> Int + N ;
741- inf_add (Inf , _N ) -> Inf .
698+ inf_add (A , B ) when is_integer (A ), is_integer (B ) -> A + B ;
699+ inf_add (Inf , Inf ) when is_atom (Inf ) -> Inf ;
700+ inf_add (Inf , _ ) when is_atom (Inf ) -> Inf ;
701+ inf_add (_ , Inf ) when is_atom (Inf ) -> Inf .
702+
703+ inf_mul (A , B ) when is_integer (A ), is_integer (B ) ->
704+ A * B ;
705+ inf_mul (A , B ) ->
706+ case {inf_sign (A ),inf_sign (B )} of
707+ {'-' ,'-' } -> '+inf' ;
708+ {'+' ,'+' } -> '+inf' ;
709+ {_ ,_ } -> '-inf'
710+ end .
711+
712+ inf_div (A , B ) when is_integer (A ), is_integer (B ) ->
713+ A div B ;
714+ inf_div (A , '+inf' ) when is_integer (A ) ->
715+ 0 .
716+
717+ inf_abs ('-inf' ) -> '+inf' ;
718+ inf_abs ('+inf' ) -> '+inf' ;
719+ inf_abs (N ) when is_integer (N ) -> abs (N ).
742720
743721inf_bsr ('-inf' , _S ) ->
744722 '-inf' ;
0 commit comments