1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.jcurl.math;
20
21 import java.io.Serializable;
22 import java.util.ArrayList;
23 import java.util.Comparator;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Map.Entry;
28
29 import org.apache.commons.logging.Log;
30 import org.jcurl.core.log.JCLoggerFactory;
31
32
33
34
35
36
37
38
39
40
41 public class CurveCombined<T extends R1RNFunction> extends R1RNFunctionImpl
42 implements Iterable<Entry<Double, T>>, Serializable {
43
44
45
46
47
48
49 public static class Part<U extends R1RNFunction> extends Number implements
50 Entry<Double, U>, Comparable<Number> {
51 private static final long serialVersionUID = 2799393238450079381L;
52 private final U curve;
53 private final Double t0;
54
55 public Part(final double t0, final U f) {
56 this.t0 = new Double(t0);
57 curve = f;
58 }
59
60 public int compareTo(final Number o2) {
61 if (doubleValue() < o2.doubleValue())
62 return -1;
63 if (doubleValue() > o2.doubleValue())
64 return 1;
65 return 0;
66 }
67
68 @Override
69 public double doubleValue() {
70 return getKey();
71 }
72
73 @Override
74 public float floatValue() {
75 return (float) doubleValue();
76 }
77
78 public Double getKey() {
79 return t0;
80 }
81
82 public U getValue() {
83 return curve;
84 }
85
86 @Override
87 public int intValue() {
88 return (int) doubleValue();
89 }
90
91 @Override
92 public long longValue() {
93 return (long) doubleValue();
94 }
95
96 public U setValue(final U value) {
97 throw new UnsupportedOperationException();
98 }
99
100 @Override
101 public String toString() {
102 return new StringBuilder().append("[").append(getKey()).append(
103 " : ").append(getValue()).append("]").toString();
104 }
105 }
106
107 private static final Log log = JCLoggerFactory
108 .getLogger(CurveCombined.class);
109
110 private static final long serialVersionUID = 5955065096153576747L;
111
112
113
114
115
116
117
118
119
120
121
122 static int binarySearch(final double[] a, int min, int max, final double key) {
123
124
125
126 for (;;) {
127 if (key == a[min])
128 return min;
129 if (key == a[max])
130 return max;
131 final int m = (max + min) / 2;
132 if (key == a[m])
133 return m;
134 if (min + 1 >= max) {
135 if (a[min] < key && key < a[max])
136 return -1 - max;
137 return -1;
138 }
139 if (key < a[m]) {
140 max = m;
141 continue;
142 } else if (key > a[m]) {
143 min = m;
144 continue;
145 }
146 }
147 }
148
149
150
151
152
153
154
155
156
157
158
159
160 static <E> int binarySearch(final List<E> a, final int fromIndex,
161 final int toIndex, final E key, final Comparator<? super E> comp) {
162 if (fromIndex > toIndex)
163 throw new IllegalArgumentException("fromIndex(" + fromIndex
164 + ") > toIndex(" + toIndex + ")");
165 if (fromIndex < 0)
166 throw new ArrayIndexOutOfBoundsException(fromIndex);
167 if (toIndex > a.size())
168 throw new ArrayIndexOutOfBoundsException(toIndex);
169
170 int low = fromIndex;
171 int high = toIndex - 1;
172 while (low <= high) {
173 final int mid = low + high >>> 1;
174 final E midVal = a.get(mid);
175 final int cmp = comp.compare(midVal, key);
176 if (cmp < 0)
177 low = mid + 1;
178 else if (cmp > 0)
179 high = mid - 1;
180 else
181 return mid;
182 }
183 return -(low + 1);
184 }
185
186
187
188
189
190
191
192
193
194
195
196
197 static <V extends R1RNFunction> int binarySearch(
198 final List<Entry<Double, V>> a, int fromIndex, int toIndex,
199 final double key) {
200 if (false) {
201 if (fromIndex > toIndex)
202 throw new IllegalArgumentException("fromIndex(" + fromIndex
203 + ") > toIndex(" + toIndex + ")");
204 if (fromIndex < 0)
205 throw new ArrayIndexOutOfBoundsException(fromIndex);
206 if (toIndex > a.size())
207 throw new ArrayIndexOutOfBoundsException(toIndex);
208
209 int low = fromIndex;
210 int high = toIndex - 1;
211 while (low <= high) {
212 final int mid = low + high >>> 1;
213 final double midVal = a.get(mid).getKey().doubleValue();
214 final int cmp = Double.compare(midVal, key);
215 if (cmp < 0)
216 low = mid + 1;
217 else if (cmp > 0)
218 high = mid - 1;
219 else
220 return mid;
221 }
222 return -(low + 1);
223 } else {
224 double fromKey = a.get(fromIndex).getKey().doubleValue();
225 double toKey = a.get(toIndex).getKey().doubleValue();
226 for (;;) {
227 if (key == fromKey)
228 return fromIndex;
229 if (key == toKey)
230 return toIndex;
231 final int midIndex = (toIndex + fromIndex) / 2;
232 final double midKey = a.get(midIndex).getKey().doubleValue();
233 if (key == midKey)
234 return midIndex;
235 if (fromIndex + 1 >= toIndex) {
236 if (fromKey < key && key < toKey)
237 return -1 - toIndex;
238 return -1;
239 }
240 if (key < midKey) {
241 toIndex = midIndex;
242 toKey = midKey;
243 continue;
244 } else if (key > midKey) {
245 fromIndex = midIndex;
246 fromKey = midKey;
247 continue;
248 }
249 }
250 }
251 }
252
253 Map<Integer, String> m;
254 private final List<Entry<Double, T>> parts = new ArrayList<Entry<Double, T>>();
255
256 public CurveCombined(final int dim) {
257 super(dim);
258 }
259
260 public void add(final double t0, final T fkt, final boolean dropTail) {
261 log.debug("");
262 if (fkt.dim() != dim())
263 throw new IllegalArgumentException();
264 if (dropTail) {
265 final int idx = findFunctionIndex(t0);
266 for (int i = parts.size() - 1; i > idx; i--)
267 parts.remove(i);
268 }
269 parts.add(new Part<T>(t0, fkt));
270 }
271
272
273
274
275
276
277
278
279
280
281
282
283
284 @Override
285 public double[] at(final double t, final int c, final double[] ret) {
286 return parts.get(findFunctionIndex(t)).getValue().at(t, c, ret);
287 }
288
289 @Override
290 public double at(final double t, final int c, final int dim) {
291 return parts.get(findFunctionIndex(t)).getValue().at(t, c, dim);
292 }
293
294 public void clear() {
295 parts.clear();
296 }
297
298
299
300
301
302
303
304 public boolean dropTail(final double t) {
305 if (Double.isNaN(t))
306 return false;
307 final int n = parts.size() - 1;
308 if (n < 0)
309 return false;
310 int j = findFunctionIndex(t);
311 if (parts.get(j).getKey() == t)
312 j += 1;
313 if (n < j)
314 return false;
315 for (int i = n; i >= j; i--)
316 parts.remove(i);
317 return true;
318 }
319
320 private int findFunctionIndex(final double t) {
321 int highIdx = parts.size() - 1;
322 if (highIdx < 0)
323 return -1;
324 double highKey = parts.get(highIdx).getKey();
325 if (t >= highKey)
326 return highIdx;
327
328 int lowIdx = 0;
329 double lowKey = parts.get(lowIdx).getKey();
330 if (t < lowKey)
331 return -1;
332
333 while (lowIdx + 1 < highIdx) {
334 final int midIdx = (highIdx + lowIdx) / 2;
335 final double midKey = parts.get(midIdx).getKey();
336
337 if (t >= midKey) {
338
339 lowIdx = midIdx;
340 lowKey = midKey;
341 } else {
342
343 highIdx = midIdx;
344 highKey = midKey;
345 }
346 }
347 return lowIdx;
348 }
349
350 public T first() {
351 if (parts.size() <= 0)
352 return null;
353 return parts.get(0).getValue();
354 }
355
356 public Iterator<Entry<Double, T>> iterator() {
357 return parts.iterator();
358 }
359
360 @Override
361 public String toString() {
362 final StringBuilder b = new StringBuilder();
363 b.append('[');
364 for (final Entry<Double, T> elem : parts)
365 b.append("x>=").append(elem.getKey()).append(" f(x)=").append(
366 elem.getValue()).append(", ");
367 if (b.length() > 2)
368 b.setLength(b.length() - 2);
369 b.append(']');
370 return b.toString();
371 }
372 }