sascha@655: package de.intevation.flys.utils; sascha@655: sascha@3776: import de.intevation.flys.artifacts.math.Linear; sascha@3776: sascha@3776: import gnu.trove.TDoubleArrayList; sascha@3776: ingo@1666: import java.util.Arrays; ingo@1666: sascha@3776: import org.apache.log4j.Logger; ingo@1666: felix@4052: /** Utils to deal with Double precision values. */ sascha@655: public class DoubleUtil sascha@655: { felix@4052: /** Private logger. */ sascha@3776: private static Logger log = Logger.getLogger(DoubleUtil.class); sascha@3776: sascha@655: public static final double DEFAULT_STEP_PRECISION = 1e6; sascha@655: sascha@655: private DoubleUtil() { sascha@655: } sascha@655: sascha@655: public static final double [] explode(double from, double to, double step) { sascha@655: return explode(from, to, step, DEFAULT_STEP_PRECISION); sascha@655: } sascha@655: sascha@655: public static final double round(double x, double precision) { sascha@655: return Math.round(x * precision)/precision; sascha@655: } sascha@655: sascha@655: public static final double round(double x) { sascha@655: return Math.round(x * DEFAULT_STEP_PRECISION)/DEFAULT_STEP_PRECISION; sascha@655: } sascha@655: sascha@655: public static final double [] explode( sascha@655: double from, sascha@655: double to, sascha@655: double step, sascha@655: double precision sascha@655: ) { sascha@655: double lower = from; sascha@655: sascha@655: double diff = to - from; sascha@655: double tmp = diff / step; sascha@655: int num = (int)Math.abs(Math.ceil(tmp)) + 1; sascha@655: teichmann@4163: if (num < 1) { teichmann@4163: return new double[0]; teichmann@4163: } teichmann@4163: sascha@655: double [] values = new double[num]; sascha@655: sascha@655: if (from > to) { sascha@655: step = -step; sascha@655: } sascha@655: ingo@1666: double max = Math.max(from, to); ingo@1666: sascha@655: for (int idx = 0; idx < num; idx++) { ingo@1666: if (lower > max) { ingo@1666: return Arrays.copyOfRange(values, 0, idx); ingo@1666: } ingo@1666: sascha@655: values[idx] = round(lower, precision); sascha@655: lower += step; sascha@655: } sascha@655: sascha@655: return values; sascha@655: } sascha@1671: sascha@1671: public static final double interpolateSorted( sascha@1671: double [] xs, sascha@1671: double [] ys, sascha@1671: double x sascha@1671: ) { sascha@1671: int lo = 0, hi = xs.length-1; sascha@1671: sascha@1671: int mid = -1; sascha@1671: sascha@1671: while (lo <= hi) { sascha@1671: mid = (lo + hi) >> 1; sascha@1671: double mx = xs[mid]; sascha@1671: if (x < mx) hi = mid - 1; sascha@1671: else if (x > mx) lo = mid + 1; sascha@1671: else return ys[mid]; sascha@1671: } sascha@1671: if (mid < lo) { sascha@1671: return lo >= xs.length sascha@1671: ? Double.NaN sascha@1671: : Linear.linear(x, xs[mid], xs[mid+1], ys[mid], ys[mid+1]); sascha@1671: } sascha@1671: return hi < 0 sascha@1671: ? Double.NaN sascha@1671: : Linear.linear(x, xs[mid-1], xs[mid], ys[mid-1], ys[mid]); sascha@1671: } sascha@1672: sascha@1672: public static final boolean isIncreasing(double [] array) { sascha@1672: int inc = 0; sascha@1672: int dec = 0; sascha@1672: int sweet = (array.length-1)/2; sascha@1672: for (int i = 1; i < array.length; ++i) { sascha@1672: if (array[i] > array[i-1]) { sascha@1672: if (++inc > sweet) { sascha@1672: return true; sascha@1672: } sascha@1672: } sascha@1672: else if (++dec > sweet) { sascha@1672: return false; sascha@1672: } sascha@1672: } sascha@1672: return inc > sweet; sascha@1672: } sascha@1672: sascha@1672: public static final double [] swap(double [] array) { sascha@1672: int lo = 0; sascha@1672: int hi = array.length-1; sascha@1672: while (hi > lo) { sascha@1672: double t = array[lo]; sascha@1672: array[lo] = array[hi]; sascha@1672: array[hi] = t; sascha@1672: ++lo; sascha@1672: --hi; sascha@1672: } sascha@1672: sascha@1672: return array; sascha@1672: } sascha@1672: sascha@1672: public static final double [] swapClone(double [] in) { sascha@1672: double [] out = new double[in.length]; sascha@1672: sascha@1672: for (int j = out.length-1, i = 0; j >= 0;) { sascha@1672: out[j--] = in[i++]; sascha@1672: } sascha@1672: sascha@1672: return out; sascha@1672: } sascha@1672: sascha@1672: public static final double [] sumDiffs(double [] in) { sascha@1672: double [] out = new double[in.length]; sascha@1672: sascha@1672: for (int i = 1; i < out.length; ++i) { sascha@1672: out[i] = out[i-1] + Math.abs(in[i-1] - in[i]); sascha@1672: } sascha@1672: sascha@1672: return out; sascha@1672: } sascha@2569: sascha@2569: public static final double [] fill(int N, double value) { sascha@2569: double [] result = new double[N]; sascha@2569: Arrays.fill(result, value); sascha@2569: return result; sascha@2569: } sascha@3776: felix@4052: felix@4052: /** Use with parseSegments. */ sascha@3776: public interface SegmentCallback { sascha@3776: void newSegment(double from, double to, double [] values); sascha@3776: } sascha@3776: felix@4052: felix@4052: /** Call callback for every string split by colon. felix@4052: * Expected format FROM:TO:VALUE1,VALUE2,VALUE3*/ sascha@3776: public static final void parseSegments( sascha@3776: String input, sascha@3776: SegmentCallback callback sascha@3776: ) { sascha@3776: TDoubleArrayList vs = new TDoubleArrayList(); sascha@3776: sascha@3776: for (String segmentStr: input.split(":")) { sascha@3776: String [] parts = segmentStr.split(";"); sascha@3776: if (parts.length < 3) { sascha@3776: log.warn("invalid segment: '" + segmentStr + "'"); sascha@3776: continue; sascha@3776: } sascha@3776: try { sascha@3776: double from = Double.parseDouble(parts[0].trim()); sascha@3776: double to = Double.parseDouble(parts[1].trim()); sascha@3776: sascha@3776: vs.resetQuick(); sascha@3776: sascha@3776: for (String valueStr: parts[2].split(",")) { sascha@3776: vs.add(round(Double.parseDouble(valueStr.trim()))); sascha@3776: } sascha@3776: sascha@3776: callback.newSegment(from, to, vs.toNativeArray()); sascha@3776: } sascha@3776: catch (NumberFormatException nfe) { sascha@3776: log.warn("invalid segment: '" + segmentStr + "'"); sascha@3776: } sascha@3776: } sascha@3776: } ingo@3785: ingo@3785: public static final boolean isValid(double [][] data) { ingo@3785: for (double [] ds: data) { ingo@3785: for (double d: ds) { ingo@3785: if (Double.isNaN(d)) { ingo@3785: return false; ingo@3785: } ingo@3785: } ingo@3785: } ingo@3785: return true; ingo@3785: } sascha@655: } sascha@655: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :