@@ -123,13 +123,18 @@ public void setBoundingBoxCacheFraction(double fraction) {
123
123
124
124
/**
125
125
* Return a new {@link Cut}, which is chosen uniformly over the space of
126
- * possible cuts for the given bounding box.
126
+ * possible cuts for a bounding box and its union with a point. The cut must
127
+ * exist unless the union box is a single point. There are floating point issues
128
+ * -- even though the original values are in float anf the calculations are in
129
+ * double, which can show up with large number of dimensions (each trigerring an
130
+ * addition/substraction).
127
131
*
128
132
* @param factor A random cut
133
+ * @param point the point whose union is taken with the box
129
134
* @param box A bounding box that we want to find a random cut for.
130
135
* @return A new Cut corresponding to a random cut in the bounding box.
131
136
*/
132
- protected Cut randomCut (double factor , float [] point , BoundingBox box ) {
137
+ protected static Cut randomCut (double factor , float [] point , BoundingBox box ) {
133
138
double range = 0.0 ;
134
139
135
140
for (int i = 0 ; i < point .length ; i ++) {
@@ -143,6 +148,9 @@ protected Cut randomCut(double factor, float[] point, BoundingBox box) {
143
148
range += maxValue - minValue ;
144
149
}
145
150
151
+ checkArgument (range > 0 , " the union is a single point " + Arrays .toString (point )
152
+ + "or the box is inappropriate, box" + box .toString () + "factor =" + factor );
153
+
146
154
double breakPoint = factor * range ;
147
155
148
156
for (int i = 0 ; i < box .getDimensions (); i ++) {
@@ -169,7 +177,50 @@ protected Cut randomCut(double factor, float[] point, BoundingBox box) {
169
177
breakPoint -= gap ;
170
178
}
171
179
172
- throw new IllegalStateException ("The break point did not lie inside the expected range" );
180
+ // if we are here then factor is likely almost 1 and we have floating point
181
+ // issues
182
+ // we will randomize between the first and the last non-zero ranges and choose
183
+ // the
184
+ // same cutValue as using nextAfter above -- we will use the factor as a seed
185
+ // and
186
+ // not be optimizing this sequel (either in execution or code) to ensure easier
187
+ // debugging
188
+ // this should be an anomaly - no pun intended.
189
+
190
+ Random rng = new Random ((long ) factor );
191
+ if (rng .nextDouble () < 0.5 ) {
192
+ for (int i = 0 ; i < box .getDimensions (); i ++) {
193
+ float minValue = (float ) box .getMinValue (i );
194
+ float maxValue = (float ) box .getMaxValue (i );
195
+ if (point [i ] < minValue ) {
196
+ minValue = point [i ];
197
+ } else if (point [i ] > maxValue ) {
198
+ maxValue = point [i ];
199
+ }
200
+ if (maxValue > minValue ) {
201
+ double cutValue = Math .nextAfter ((float ) maxValue , minValue );
202
+ return new Cut (i , cutValue );
203
+ }
204
+ }
205
+ } else {
206
+ for (int i = box .getDimensions () - 1 ; i >= 0 ; i --) {
207
+ float minValue = (float ) box .getMinValue (i );
208
+ float maxValue = (float ) box .getMaxValue (i );
209
+ if (point [i ] < minValue ) {
210
+ minValue = point [i ];
211
+ } else if (point [i ] > maxValue ) {
212
+ maxValue = point [i ];
213
+ }
214
+ if (maxValue > minValue ) {
215
+ double cutValue = Math .nextAfter ((float ) maxValue , minValue );
216
+ return new Cut (i , cutValue );
217
+ }
218
+ }
219
+ }
220
+
221
+ throw new IllegalStateException ("The break point did not lie inside the expected range; factor " + factor
222
+ + ", point " + Arrays .toString (point ) + " box " + box .toString ());
223
+
173
224
}
174
225
175
226
public Integer addPoint (Integer pointIndex , long sequenceIndex ) {
0 commit comments