Mercurial > dive4elements > river
view flys-artifacts/src/main/java/de/intevation/flys/utils/DoubleUtil.java @ 5690:b85df73edef0
merge
author | Tom Gottfried <tom.gottfried@intevation.de> |
---|---|
date | Fri, 12 Apr 2013 19:52:15 +0200 |
parents | 240ff7aeb6de |
children |
line wrap: on
line source
package de.intevation.flys.utils; import de.intevation.flys.artifacts.math.Linear; import gnu.trove.TDoubleArrayList; import java.util.Arrays; import org.apache.log4j.Logger; /** Utils to deal with Double precision values. */ public class DoubleUtil { /** Private logger. */ private static Logger log = Logger.getLogger(DoubleUtil.class); public static final double DEFAULT_STEP_PRECISION = 1e6; /** EPSILON for comparison of double precision values. */ public static final double EPSILON = 1e-4; private DoubleUtil() { } public static final double [] explode(double from, double to, double step) { return explode(from, to, step, DEFAULT_STEP_PRECISION); } public static final double round(double x, double precision) { return Math.round(x * precision)/precision; } public static final double round(double x) { return Math.round(x * DEFAULT_STEP_PRECISION)/DEFAULT_STEP_PRECISION; } /** * Returns array with values from parameter from to to with given step width. * from and to are included. */ public static final double [] explode( double from, double to, double step, double precision ) { double lower = from; double diff = to - from; double tmp = diff / step; int num = (int)Math.abs(Math.ceil(tmp)) + 1; if (num < 1) { return new double[0]; } double [] values = new double[num]; if (from > to) { step = -step; } double max = Math.max(from, to); for (int idx = 0; idx < num; idx++) { if (lower - max > EPSILON) { return Arrays.copyOfRange(values, 0, idx); } values[idx] = round(lower, precision); lower += step; } return values; } public static final double interpolateSorted( double [] xs, double [] ys, double x ) { int lo = 0, hi = xs.length-1; int mid = -1; while (lo <= hi) { mid = (lo + hi) >> 1; double mx = xs[mid]; if (x < mx) hi = mid - 1; else if (x > mx) lo = mid + 1; else return ys[mid]; } if (mid < lo) { return lo >= xs.length ? Double.NaN : Linear.linear(x, xs[mid], xs[mid+1], ys[mid], ys[mid+1]); } return hi < 0 ? Double.NaN : Linear.linear(x, xs[mid-1], xs[mid], ys[mid-1], ys[mid]); } public static final boolean isIncreasing(double [] array) { int inc = 0; int dec = 0; int sweet = (array.length-1)/2; for (int i = 1; i < array.length; ++i) { if (array[i] > array[i-1]) { if (++inc > sweet) { return true; } } else if (++dec > sweet) { return false; } } return inc > sweet; } public static final double [] swap(double [] array) { int lo = 0; int hi = array.length-1; while (hi > lo) { double t = array[lo]; array[lo] = array[hi]; array[hi] = t; ++lo; --hi; } return array; } public static final double [] swapClone(double [] in) { double [] out = new double[in.length]; for (int j = out.length-1, i = 0; j >= 0;) { out[j--] = in[i++]; } return out; } public static final double [] sumDiffs(double [] in) { double [] out = new double[in.length]; for (int i = 1; i < out.length; ++i) { out[i] = out[i-1] + Math.abs(in[i-1] - in[i]); } return out; } public static final double [] fill(int N, double value) { double [] result = new double[N]; Arrays.fill(result, value); return result; } /** Use with parseSegments. */ public interface SegmentCallback { void newSegment(double from, double to, double [] values); } /** Call callback for every string split by colon. * Expected format FROM:TO:VALUE1,VALUE2,VALUE3*/ public static final void parseSegments( String input, SegmentCallback callback ) { TDoubleArrayList vs = new TDoubleArrayList(); for (String segmentStr: input.split(":")) { String [] parts = segmentStr.split(";"); if (parts.length < 3) { log.warn("invalid segment: '" + segmentStr + "'"); continue; } try { double from = Double.parseDouble(parts[0].trim()); double to = Double.parseDouble(parts[1].trim()); vs.resetQuick(); for (String valueStr: parts[3].split(",")) { vs.add(round(Double.parseDouble(valueStr.trim()))); } callback.newSegment(from, to, vs.toNativeArray()); } catch (NumberFormatException nfe) { log.warn("invalid segment: '" + segmentStr + "'"); } } } public static final boolean isValid(double [][] data) { for (double [] ds: data) { for (double d: ds) { if (Double.isNaN(d)) { return false; } } } return true; } /** In an array of doubles, search and return the maximum value. */ public static final double maxInArray(double[] values) { double max = - Double.MAX_VALUE; for (double d: values) { if (d > max) max = d; } return max; } public static void removeNaNs(TDoubleArrayList [] arrays) { int dest = 0; int A = arrays.length; int N = arrays[0].size(); OUTER: for (int i = 0; i < N; ++i) { for (int j = 0; j < A; ++j) { TDoubleArrayList a = arrays[j]; double v = a.getQuick(i); if (Double.isNaN(v)) { continue OUTER; } a.setQuick(dest, v); } ++dest; } if (dest < N) { for (int i = 0; i < A; ++i) { arrays[i].remove(dest, N-dest); } } } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :