@@ -127,25 +127,56 @@ private IteratingResult nextValueAt(
127
127
final int maxIteration )
128
128
throws ExceededMaxIterationException , SchedulingInterruptedException
129
129
{
130
+ // the number of possible values may be less than the number of iterations, so stop after all have been visited.
131
+ long numTimepoints = minus (minus (max .in (Duration .MICROSECONDS ), min .in (Duration .MICROSECONDS )), 1 );
132
+ long maxIters = Long .min (maxIteration , numTimepoints );
130
133
var cur = init ;
131
- int i = 0 ;
134
+ long i = 0 ;
132
135
do {
133
136
//we should not come back to previously visited values
134
137
if (!history .alreadyVisited (cur ) && cur .between (min , max )) {
135
138
i ++;
136
139
try {
137
140
final var value = function .valueAt (cur , history );
138
- return new IteratingResult (new FunctionCoordinate <>(cur , value ), i );
141
+ return new IteratingResult (new FunctionCoordinate <>(cur , value ), (( Long ) i ). intValue () );
139
142
} catch (DiscontinuityException e ) {
140
143
//nothing, keep iterating
141
144
}
142
145
}
143
146
cur = chooseRandomX (min , max );
144
- //if min == max , another call to random will have no effect and thus we should exit
145
- } while (i < maxIteration && ! min . isEqualTo ( max ) );
147
+ //if all timepoints have been visited , another call to random will have no effect and thus we should exit
148
+ } while (i < maxIters );
146
149
throw new ExceededMaxIterationException ();
147
150
}
148
151
152
+ /**
153
+ * Addition of longs with safety from overflow
154
+ */
155
+ private static long plus (final long rd1 , final long rd2 ) {
156
+ long result ;
157
+ // check for overflow
158
+ if ( rd1 >= 0 && Long .MAX_VALUE - rd1 <= rd2 ) {
159
+ result = Long .MAX_VALUE ;
160
+ } else if ( rd1 < 0 && Long .MIN_VALUE - rd1 >= rd2 ) {
161
+ result = Long .MIN_VALUE ;
162
+ } else {
163
+ result = rd1 + rd2 ;
164
+ }
165
+ return result ;
166
+ }
167
+
168
+ /**
169
+ * Subtraction of longs with safety from overflow
170
+ */
171
+ private static long minus (final long rd1 , final long rd2 ) {
172
+ long result ;
173
+ // use plus, but don't risk trying to negate +/-inf
174
+ if ( rd2 == Long .MAX_VALUE ) result = plus ( rd1 , Long .MIN_VALUE );
175
+ else if ( rd2 == Long .MIN_VALUE ) result = plus ( rd1 , Long .MAX_VALUE );
176
+ else result = plus (rd1 , -rd2 );
177
+ return result ;
178
+ }
179
+
149
180
/**
150
181
* Solves x s.t. f(x) = y by transforming it to the equivalent rootfinding problem x s.t. f(x) - y = 0
151
182
* @param f the function
@@ -182,6 +213,7 @@ public RootFindingResult<Duration, Metadata> findRoot(
182
213
public Duration valueAt (final Duration x , final History <Duration , Metadata > history )
183
214
throws EquationSolvingAlgorithms .DiscontinuityException , SchedulingInterruptedException
184
215
{
216
+ // don't add value to history -- it breaks things
185
217
return f .valueAt (x , history ).minus (y );
186
218
}
187
219
};
0 commit comments