44 This file is part of Decider.
55*/
66using System ;
7+ using System . Linq ;
78
89using Decider . Csp . BaseTypes ;
910
1011namespace Decider . Csp . Integer
1112{
1213 public class ExpressionInteger : Expression < int >
1314 {
15+ private static int ClampToInt ( long value ) =>
16+ ( int ) Math . Max ( int . MinValue , Math . Min ( int . MaxValue , value ) ) ;
17+
1418 public static ExpressionInteger operator + ( ExpressionInteger left , ExpressionInteger right )
1519 {
1620 return new ExpressionInteger ( left , right )
1721 {
18- evaluate = ( l , r ) => l . Value + r . Value ,
22+ evaluate = ( l , r ) => ClampToInt ( ( long ) l . Value + r . Value ) ,
1923 evaluateBounds = ( l , r ) =>
2024 {
2125 var leftBounds = l . GetUpdatedBounds ( ) ;
2226 var rightBounds = r . GetUpdatedBounds ( ) ;
2327
2428 return new Bounds < int >
2529 (
26- ( int ) Math . Max ( int . MinValue , Math . Min ( int . MaxValue , ( long ) leftBounds . LowerBound + rightBounds . LowerBound ) ) ,
27- ( int ) Math . Min ( int . MaxValue , Math . Max ( int . MinValue , ( long ) leftBounds . UpperBound + rightBounds . UpperBound ) )
30+ ClampToInt ( ( long ) leftBounds . LowerBound + rightBounds . LowerBound ) ,
31+ ClampToInt ( ( long ) leftBounds . UpperBound + rightBounds . UpperBound )
2832 ) ;
2933 } ,
3034 propagator = ( first , second , enforce ) =>
3135 {
3236 var result = ConstraintOperationResult . Undecided ;
33- if ( first . Bounds . LowerBound < enforce . LowerBound - second . Bounds . UpperBound )
37+ var newBound = ClampToInt ( ( long ) enforce . LowerBound - second . Bounds . UpperBound ) ;
38+ if ( first . Bounds . LowerBound < newBound )
3439 {
35- first . Bounds . LowerBound = enforce . LowerBound - second . Bounds . UpperBound ;
40+ first . Bounds . LowerBound = newBound ;
3641 result = ConstraintOperationResult . Propagated ;
3742 }
3843
39- if ( first . Bounds . UpperBound > enforce . UpperBound - second . Bounds . LowerBound )
44+ newBound = ClampToInt ( ( long ) enforce . UpperBound - second . Bounds . LowerBound ) ;
45+ if ( first . Bounds . UpperBound > newBound )
4046 {
41- first . Bounds . UpperBound = enforce . UpperBound - second . Bounds . LowerBound ;
47+ first . Bounds . UpperBound = newBound ;
4248 result = ConstraintOperationResult . Propagated ;
4349 }
4450
45- if ( second . Bounds . LowerBound < enforce . LowerBound - first . Bounds . UpperBound )
51+ newBound = ClampToInt ( ( long ) enforce . LowerBound - first . Bounds . UpperBound ) ;
52+ if ( second . Bounds . LowerBound < newBound )
4653 {
47- second . Bounds . LowerBound = enforce . LowerBound - first . Bounds . UpperBound ;
54+ second . Bounds . LowerBound = newBound ;
4855 result = ConstraintOperationResult . Propagated ;
4956 }
5057
51- if ( second . Bounds . UpperBound > enforce . UpperBound - first . Bounds . LowerBound )
58+ newBound = ClampToInt ( ( long ) enforce . UpperBound - first . Bounds . LowerBound ) ;
59+ if ( second . Bounds . UpperBound > newBound )
5260 {
53- second . Bounds . UpperBound = enforce . UpperBound - first . Bounds . LowerBound ;
61+ second . Bounds . UpperBound = newBound ;
5462 result = ConstraintOperationResult . Propagated ;
5563 }
5664
@@ -66,42 +74,42 @@ public class ExpressionInteger : Expression<int>
6674 {
6775 var expression = new ExpressionInteger ( left , right )
6876 {
69- evaluate = ( l , r ) => l . Value - r . Value ,
77+ evaluate = ( l , r ) => ClampToInt ( ( long ) l . Value - r . Value ) ,
7078 evaluateBounds = ( l , r ) =>
7179 {
7280 var leftBounds = l . GetUpdatedBounds ( ) ;
7381 var rightBounds = r . GetUpdatedBounds ( ) ;
7482
7583 return new Bounds < int >
7684 (
77- ( int ) Math . Max ( int . MinValue , Math . Min ( int . MaxValue , ( long ) leftBounds . LowerBound - rightBounds . UpperBound ) ) ,
78- ( int ) Math . Min ( int . MaxValue , Math . Max ( int . MinValue , ( long ) leftBounds . UpperBound - rightBounds . LowerBound ) )
85+ ClampToInt ( ( long ) leftBounds . LowerBound - rightBounds . UpperBound ) ,
86+ ClampToInt ( ( long ) leftBounds . UpperBound - rightBounds . LowerBound )
7987 ) ;
8088 } ,
8189 propagator = ( first , second , enforce ) =>
8290 {
8391 var result = ConstraintOperationResult . Undecided ;
8492 if ( first . Bounds . LowerBound < enforce . LowerBound + second . Bounds . LowerBound )
8593 {
86- first . Bounds . LowerBound = enforce . LowerBound + second . Bounds . LowerBound ;
94+ first . Bounds . LowerBound = ClampToInt ( ( long ) enforce . LowerBound + second . Bounds . LowerBound ) ;
8795 result = ConstraintOperationResult . Propagated ;
8896 }
8997
9098 if ( first . Bounds . UpperBound > enforce . UpperBound + second . Bounds . UpperBound )
9199 {
92- first . Bounds . UpperBound = enforce . UpperBound + second . Bounds . UpperBound ;
100+ first . Bounds . UpperBound = ClampToInt ( ( long ) enforce . UpperBound + second . Bounds . UpperBound ) ;
93101 result = ConstraintOperationResult . Propagated ;
94102 }
95103
96104 if ( second . Bounds . LowerBound < first . Bounds . LowerBound - enforce . UpperBound )
97105 {
98- second . Bounds . LowerBound = first . Bounds . LowerBound - enforce . UpperBound ;
106+ second . Bounds . LowerBound = ClampToInt ( ( long ) first . Bounds . LowerBound - enforce . UpperBound ) ;
99107 result = ConstraintOperationResult . Propagated ;
100108 }
101109
102110 if ( second . Bounds . UpperBound > first . Bounds . UpperBound - enforce . LowerBound )
103111 {
104- second . Bounds . UpperBound = first . Bounds . UpperBound - enforce . LowerBound ;
112+ second . Bounds . UpperBound = ClampToInt ( ( long ) first . Bounds . UpperBound - enforce . LowerBound ) ;
105113 result = ConstraintOperationResult . Propagated ;
106114 }
107115
@@ -134,7 +142,7 @@ public class ExpressionInteger : Expression<int>
134142 {
135143 return new ExpressionInteger ( left , right )
136144 {
137- evaluate = ( l , r ) => l . Value / r . Value ,
145+ evaluate = ( l , r ) => ( l . Value == int . MinValue && r . Value == - 1 ) ? int . MaxValue : l . Value / r . Value ,
138146 evaluateBounds = ( l , r ) =>
139147 {
140148 var leftBounds = l . GetUpdatedBounds ( ) ;
@@ -151,13 +159,13 @@ public class ExpressionInteger : Expression<int>
151159 var result = ConstraintOperationResult . Undecided ;
152160 if ( first . Bounds . LowerBound < second . Bounds . LowerBound * enforce . LowerBound )
153161 {
154- first . Bounds . LowerBound = second . Bounds . LowerBound * enforce . LowerBound ;
162+ first . Bounds . LowerBound = ClampToInt ( ( long ) second . Bounds . LowerBound * enforce . LowerBound ) ;
155163 result = ConstraintOperationResult . Propagated ;
156164 }
157165
158166 if ( first . Bounds . UpperBound > second . Bounds . UpperBound * enforce . UpperBound )
159167 {
160- first . Bounds . UpperBound = second . Bounds . UpperBound * enforce . UpperBound ;
168+ first . Bounds . UpperBound = ClampToInt ( ( long ) second . Bounds . UpperBound * enforce . UpperBound ) ;
161169 result = ConstraintOperationResult . Propagated ;
162170 }
163171
@@ -191,17 +199,21 @@ public class ExpressionInteger : Expression<int>
191199 {
192200 return new ExpressionInteger ( left , right )
193201 {
194- evaluate = ( l , r ) => l . Value * r . Value ,
202+ evaluate = ( l , r ) => ClampToInt ( ( long ) l . Value * r . Value ) ,
195203 evaluateBounds = ( l , r ) =>
196204 {
197205 var leftBounds = l . GetUpdatedBounds ( ) ;
198206 var rightBounds = r . GetUpdatedBounds ( ) ;
199207
200- return new Bounds < int >
201- (
202- ( leftBounds . LowerBound == 0 || rightBounds . LowerBound == 0 ) ? 0 : ( ( leftBounds . LowerBound < 0 ) != ( rightBounds . LowerBound < 0 ) && Math . Abs ( ( long ) leftBounds . LowerBound ) > int . MaxValue / Math . Abs ( ( long ) rightBounds . LowerBound ) ) ? int . MinValue : leftBounds . LowerBound * rightBounds . LowerBound ,
203- ( leftBounds . UpperBound > 0 && rightBounds . UpperBound > 0 && leftBounds . UpperBound > int . MaxValue / rightBounds . UpperBound ) ? int . MaxValue : leftBounds . UpperBound * rightBounds . UpperBound
204- ) ;
208+ var products = new [ ]
209+ {
210+ ( long ) leftBounds . LowerBound * rightBounds . LowerBound ,
211+ ( long ) leftBounds . LowerBound * rightBounds . UpperBound ,
212+ ( long ) leftBounds . UpperBound * rightBounds . LowerBound ,
213+ ( long ) leftBounds . UpperBound * rightBounds . UpperBound
214+ } ;
215+
216+ return new Bounds < int > ( ClampToInt ( products . Min ( ) ) , ClampToInt ( products . Max ( ) ) ) ;
205217 } ,
206218 propagator = ( first , second , enforce ) =>
207219 {
0 commit comments