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@4433:      * 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:     }
felix@4340: 
felix@4340: 
felix@4340:     /** In an array of doubles, search and return the maximum value. */
felix@4340:     public static final double maxInArray(double[] values) {
felix@4340:         double max = - Double.MAX_VALUE;
felix@4340:         for (double d: values) {
felix@4340:             if (d > max) max = d;
felix@4340:         }
felix@4340:         return max;
felix@4340:     }
sascha@655: }
sascha@655: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :