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 :

http://dive4elements.wald.intevation.org