Mercurial > dive4elements > river
comparison artifacts/src/main/java/org/dive4elements/river/utils/DoubleUtil.java @ 5838:5aa05a7a34b7
Rename modules to more fitting names.
author | Sascha L. Teichmann <teichmann@intevation.de> |
---|---|
date | Thu, 25 Apr 2013 15:23:37 +0200 |
parents | flys-artifacts/src/main/java/org/dive4elements/river/utils/DoubleUtil.java@bd047b71ab37 |
children | 4897a58c8746 |
comparison
equal
deleted
inserted
replaced
5837:d9901a08d0a6 | 5838:5aa05a7a34b7 |
---|---|
1 package org.dive4elements.river.utils; | |
2 | |
3 import org.dive4elements.river.artifacts.math.Linear; | |
4 | |
5 import gnu.trove.TDoubleArrayList; | |
6 | |
7 import java.util.Arrays; | |
8 | |
9 import org.apache.log4j.Logger; | |
10 | |
11 /** Utils to deal with Double precision values. */ | |
12 public class DoubleUtil | |
13 { | |
14 /** Private logger. */ | |
15 private static Logger log = Logger.getLogger(DoubleUtil.class); | |
16 | |
17 public static final double DEFAULT_STEP_PRECISION = 1e6; | |
18 | |
19 /** EPSILON for comparison of double precision values. */ | |
20 public static final double EPSILON = 1e-4; | |
21 | |
22 private DoubleUtil() { | |
23 } | |
24 | |
25 public static final double [] explode(double from, double to, double step) { | |
26 return explode(from, to, step, DEFAULT_STEP_PRECISION); | |
27 } | |
28 | |
29 public static final double round(double x, double precision) { | |
30 return Math.round(x * precision)/precision; | |
31 } | |
32 | |
33 public static final double round(double x) { | |
34 return Math.round(x * DEFAULT_STEP_PRECISION)/DEFAULT_STEP_PRECISION; | |
35 } | |
36 | |
37 /** | |
38 * Returns array with values from parameter from to to with given step width. | |
39 * from and to are included. | |
40 */ | |
41 public static final double [] explode( | |
42 double from, | |
43 double to, | |
44 double step, | |
45 double precision | |
46 ) { | |
47 double lower = from; | |
48 | |
49 double diff = to - from; | |
50 double tmp = diff / step; | |
51 int num = (int)Math.abs(Math.ceil(tmp)) + 1; | |
52 | |
53 if (num < 1) { | |
54 return new double[0]; | |
55 } | |
56 | |
57 double [] values = new double[num]; | |
58 | |
59 if (from > to) { | |
60 step = -step; | |
61 } | |
62 | |
63 double max = Math.max(from, to); | |
64 | |
65 for (int idx = 0; idx < num; idx++) { | |
66 if (lower - max > EPSILON) { | |
67 return Arrays.copyOfRange(values, 0, idx); | |
68 } | |
69 | |
70 values[idx] = round(lower, precision); | |
71 lower += step; | |
72 } | |
73 | |
74 return values; | |
75 } | |
76 | |
77 public static final double interpolateSorted( | |
78 double [] xs, | |
79 double [] ys, | |
80 double x | |
81 ) { | |
82 int lo = 0, hi = xs.length-1; | |
83 | |
84 int mid = -1; | |
85 | |
86 while (lo <= hi) { | |
87 mid = (lo + hi) >> 1; | |
88 double mx = xs[mid]; | |
89 if (x < mx) hi = mid - 1; | |
90 else if (x > mx) lo = mid + 1; | |
91 else return ys[mid]; | |
92 } | |
93 if (mid < lo) { | |
94 return lo >= xs.length | |
95 ? Double.NaN | |
96 : Linear.linear(x, xs[mid], xs[mid+1], ys[mid], ys[mid+1]); | |
97 } | |
98 return hi < 0 | |
99 ? Double.NaN | |
100 : Linear.linear(x, xs[mid-1], xs[mid], ys[mid-1], ys[mid]); | |
101 } | |
102 | |
103 public static final boolean isIncreasing(double [] array) { | |
104 int inc = 0; | |
105 int dec = 0; | |
106 int sweet = (array.length-1)/2; | |
107 for (int i = 1; i < array.length; ++i) { | |
108 if (array[i] > array[i-1]) { | |
109 if (++inc > sweet) { | |
110 return true; | |
111 } | |
112 } | |
113 else if (++dec > sweet) { | |
114 return false; | |
115 } | |
116 } | |
117 return inc > sweet; | |
118 } | |
119 | |
120 public static final double [] swap(double [] array) { | |
121 int lo = 0; | |
122 int hi = array.length-1; | |
123 while (hi > lo) { | |
124 double t = array[lo]; | |
125 array[lo] = array[hi]; | |
126 array[hi] = t; | |
127 ++lo; | |
128 --hi; | |
129 } | |
130 | |
131 return array; | |
132 } | |
133 | |
134 public static final double [] swapClone(double [] in) { | |
135 double [] out = new double[in.length]; | |
136 | |
137 for (int j = out.length-1, i = 0; j >= 0;) { | |
138 out[j--] = in[i++]; | |
139 } | |
140 | |
141 return out; | |
142 } | |
143 | |
144 public static final double [] sumDiffs(double [] in) { | |
145 double [] out = new double[in.length]; | |
146 | |
147 for (int i = 1; i < out.length; ++i) { | |
148 out[i] = out[i-1] + Math.abs(in[i-1] - in[i]); | |
149 } | |
150 | |
151 return out; | |
152 } | |
153 | |
154 public static final double [] fill(int N, double value) { | |
155 double [] result = new double[N]; | |
156 Arrays.fill(result, value); | |
157 return result; | |
158 } | |
159 | |
160 | |
161 /** Use with parseSegments. */ | |
162 public interface SegmentCallback { | |
163 void newSegment(double from, double to, double [] values); | |
164 } | |
165 | |
166 | |
167 /** Call callback for every string split by colon. | |
168 * Expected format FROM:TO:VALUE1,VALUE2,VALUE3*/ | |
169 public static final void parseSegments( | |
170 String input, | |
171 SegmentCallback callback | |
172 ) { | |
173 TDoubleArrayList vs = new TDoubleArrayList(); | |
174 | |
175 for (String segmentStr: input.split(":")) { | |
176 String [] parts = segmentStr.split(";"); | |
177 if (parts.length < 3) { | |
178 log.warn("invalid segment: '" + segmentStr + "'"); | |
179 continue; | |
180 } | |
181 try { | |
182 double from = Double.parseDouble(parts[0].trim()); | |
183 double to = Double.parseDouble(parts[1].trim()); | |
184 | |
185 vs.resetQuick(); | |
186 | |
187 for (String valueStr: parts[3].split(",")) { | |
188 vs.add(round(Double.parseDouble(valueStr.trim()))); | |
189 } | |
190 | |
191 callback.newSegment(from, to, vs.toNativeArray()); | |
192 } | |
193 catch (NumberFormatException nfe) { | |
194 log.warn("invalid segment: '" + segmentStr + "'"); | |
195 } | |
196 } | |
197 } | |
198 | |
199 public static final boolean isValid(double [][] data) { | |
200 for (double [] ds: data) { | |
201 for (double d: ds) { | |
202 if (Double.isNaN(d)) { | |
203 return false; | |
204 } | |
205 } | |
206 } | |
207 return true; | |
208 } | |
209 | |
210 | |
211 /** In an array of doubles, search and return the maximum value. */ | |
212 public static final double maxInArray(double[] values) { | |
213 double max = - Double.MAX_VALUE; | |
214 for (double d: values) { | |
215 if (d > max) max = d; | |
216 } | |
217 return max; | |
218 } | |
219 | |
220 public static void removeNaNs(TDoubleArrayList [] arrays) { | |
221 | |
222 int dest = 0; | |
223 | |
224 int A = arrays.length; | |
225 int N = arrays[0].size(); | |
226 | |
227 OUTER: for (int i = 0; i < N; ++i) { | |
228 for (int j = 0; j < A; ++j) { | |
229 TDoubleArrayList a = arrays[j]; | |
230 double v = a.getQuick(i); | |
231 if (Double.isNaN(v)) { | |
232 continue OUTER; | |
233 } | |
234 a.setQuick(dest, v); | |
235 } | |
236 ++dest; | |
237 } | |
238 | |
239 if (dest < N) { | |
240 for (int i = 0; i < A; ++i) { | |
241 arrays[i].remove(dest, N-dest); | |
242 } | |
243 } | |
244 } | |
245 } | |
246 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : |