Example usage for java.lang Double isInfinite

List of usage examples for java.lang Double isInfinite

Introduction

In this page you can find the example usage for java.lang Double isInfinite.

Prototype

public static boolean isInfinite(double v) 

Source Link

Document

Returns true if the specified number is infinitely large in magnitude, false otherwise.

Usage

From source file:org.kalypso.jts.JTSUtilities.java

/**
 * This function returns the nearest point on the line within a distance of the provided point.
 * //from  www  .  ja  va2s  .  c  om
 * @param line
 *          The points on this line will be evaluated.
 * @param point
 *          This is the reference point.
 * @param distance
 *          The nearest point of line segment, the point is in must lie within the given distance. If you provide a
 *          invalid distance such as {@link Double#NaN}, {@link Double#NEGATIVE_INFINITY}, {@link Double#POSITIVE_INFINITY} or a negative number, a default distance ({@link #TOLERANCE} =
 *          {@value #TOLERANCE}) will be used.
 * @return The point, if one could be found or null.
 */
public static Point findPointInLine(final LineString line, final Point point, double distance) {
    /* Check for intersection. */
    if (point.distance(line) >= TOLERANCE)
        throw new IllegalStateException("The point does not lie on the line ...");

    /* Check the distance. */
    if (Double.isNaN(distance) || Double.isInfinite(distance))
        distance = TOLERANCE;

    /* Find the line segment, this point is in. */
    final LineSegment segment = findLineSegment(line, point);
    if (segment == null)
        return null;

    /* Check the distance to the reference point. */
    final Coordinate referenceCoordinate = point.getCoordinate();
    final double distance0 = segment.getCoordinate(0).distance(referenceCoordinate);
    final double distance1 = segment.getCoordinate(1).distance(referenceCoordinate);
    Coordinate closestCoordinate = null;
    if (distance0 <= distance1)
        closestCoordinate = segment.getCoordinate(0);
    else
        closestCoordinate = segment.getCoordinate(1);

    if (closestCoordinate.distance(referenceCoordinate) <= distance) {
        final GeometryFactory factory = new GeometryFactory(line.getPrecisionModel(), line.getSRID());
        return factory.createPoint(closestCoordinate);
    }

    return null;
}

From source file:geogebra.common.kernel.algos.AlgoFunctionAreaSums.java

private boolean functionDefined(double ad, double bd) {
    double interval = (bd - ad) / CHECKPOINTS;
    for (double temp = ad; (interval > 0 && temp < bd) || (interval < 0 && temp > bd); temp += interval) {
        double val = f.evaluate(temp);
        if (Double.isNaN(val) || Double.isInfinite(val)) {
            return false;
        }/*from w w  w. j av a2  s  .co  m*/
    }
    double val = f.evaluate(bd);
    if (Double.isNaN(val) || Double.isInfinite(val))
        return false;
    return true;
}

From source file:org.eclipse.january.dataset.AbstractDataset.java

/**
 * Calculate minimum and maximum for a dataset
 * @param ignoreNaNs if true, ignore NaNs
 * @param ignoreInfs if true, ignore infinities
 *///from  w  w  w  .  jav a2  s.  c  o  m
protected void calculateMaxMin(final boolean ignoreNaNs, final boolean ignoreInfs) {
    IndexIterator iter = getIterator();
    double amax = Double.NEGATIVE_INFINITY;
    double amin = Double.POSITIVE_INFINITY;
    double hash = 0;
    boolean hasNaNs = false;

    while (iter.hasNext()) {
        final double val = getElementDoubleAbs(iter.index);
        if (Double.isNaN(val)) {
            hash = (hash * 19) % Integer.MAX_VALUE;
            if (ignoreNaNs)
                continue;
            hasNaNs = true;
        } else if (Double.isInfinite(val)) {
            hash = (hash * 19) % Integer.MAX_VALUE;
            if (ignoreInfs)
                continue;
        } else {
            hash = (hash * 19 + val) % Integer.MAX_VALUE;
        }

        if (val > amax) {
            amax = val;
        }
        if (val < amin) {
            amin = val;
        }
    }

    int ihash = ((int) hash) * 19 + getDType() * 17 + getElementsPerItem();
    setStoredValue(storeName(ignoreNaNs, ignoreInfs, STORE_SHAPELESS_HASH), ihash);
    storedValues.put(storeName(ignoreNaNs, ignoreInfs, STORE_MAX),
            hasNaNs ? Double.NaN : fromDoubleToNumber(amax));
    storedValues.put(storeName(ignoreNaNs, ignoreInfs, STORE_MIN),
            hasNaNs ? Double.NaN : fromDoubleToNumber(amin));
}

From source file:org.eclipse.january.dataset.AbstractDataset.java

/**
 * Calculate summary statistics for a dataset
 * @param ignoreNaNs if true, ignore NaNs
 * @param ignoreInfs if true, ignore infinities
 * @param name/*from   w w w .  j a  va 2 s. c  o  m*/
 */
protected void calculateSummaryStats(final boolean ignoreNaNs, final boolean ignoreInfs, final String name) {
    final IndexIterator iter = getIterator();
    final SummaryStatistics stats = new SummaryStatistics();
    //sum of logs is slow and we dont use it, so blocking its calculation here
    stats.setSumLogImpl(new NullStorelessUnivariateStatistic());

    if (storedValues == null || !storedValues.containsKey(STORE_HASH)) {
        boolean hasNaNs = false;
        double hash = 0;

        while (iter.hasNext()) {
            final double val = getElementDoubleAbs(iter.index);
            if (Double.isNaN(val)) {
                hash = (hash * 19) % Integer.MAX_VALUE;
                if (ignoreNaNs)
                    continue;
                hasNaNs = true;
            } else if (Double.isInfinite(val)) {
                hash = (hash * 19) % Integer.MAX_VALUE;
                if (ignoreInfs)
                    continue;
            } else {
                hash = (hash * 19 + val) % Integer.MAX_VALUE;
            }
            stats.addValue(val);
        }

        int ihash = ((int) hash) * 19 + getDType() * 17 + getElementsPerItem();
        setStoredValue(storeName(ignoreNaNs, ignoreInfs, STORE_SHAPELESS_HASH), ihash);
        storedValues.put(storeName(ignoreNaNs, ignoreInfs, STORE_MAX),
                hasNaNs ? Double.NaN : fromDoubleToNumber(stats.getMax()));
        storedValues.put(storeName(ignoreNaNs, ignoreInfs, STORE_MIN),
                hasNaNs ? Double.NaN : fromDoubleToNumber(stats.getMin()));
        storedValues.put(name, stats);
    } else {
        while (iter.hasNext()) {
            final double val = getElementDoubleAbs(iter.index);
            if (ignoreNaNs && Double.isNaN(val)) {
                continue;
            }
            if (ignoreInfs && Double.isInfinite(val)) {
                continue;
            }

            stats.addValue(val);
        }

        storedValues.put(name, stats);
    }
}

From source file:edu.cmu.tetrad.sem.SemIm.java

/**
 * Simulates data from this Sem using a Cholesky decomposition of the
 * implied covariance matrix. This method works even when the underlying
 * graph is cyclic./*ww w . ja v  a2 s  .  c  o  m*/
 *
 * @param sampleSize      the number of rows of data to simulate.
 * @param latentDataSaved True iff data for latents should be saved.
 */
public DataSet simulateDataCholesky(int sampleSize, boolean latentDataSaved) {
    List<Node> variables = new LinkedList<Node>();

    if (latentDataSaved) {
        for (Node node : getVariableNodes()) {
            variables.add(node);
        }
    } else {
        for (Node node : getMeasuredNodes()) {
            variables.add(node);
        }
    }

    List<Node> newVariables = new ArrayList<Node>();

    for (Node node : variables) {
        ContinuousVariable continuousVariable = new ContinuousVariable(node.getName());
        continuousVariable.setNodeType(node.getNodeType());
        newVariables.add(continuousVariable);
    }

    TetradMatrix impliedCovar = implCovar();

    DataSet fullDataSet = new ColtDataSet(sampleSize, newVariables);
    TetradMatrix cholesky = MatrixUtils.choleskyC(impliedCovar);

    // Simulate the data by repeatedly calling the Cholesky.exogenousData
    // method. Store only the data for the measured variables.
    ROW: for (int row = 0; row < sampleSize; row++) {

        // Step 1. Generate normal samples.
        double exoData[] = new double[cholesky.rows()];

        for (int i = 0; i < exoData.length; i++) {
            exoData[i] = RandomUtil.getInstance().nextNormal(0, 1);
            //            exoData[i] = randomUtil.nextUniform(-1, 1);
        }

        // Step 2. Multiply by cholesky to get correct covariance.
        double point[] = new double[exoData.length];

        for (int i = 0; i < exoData.length; i++) {
            double sum = 0.0;

            for (int j = 0; j <= i; j++) {
                sum += cholesky.get(i, j) * exoData[j];
            }

            point[i] = sum;
        }

        double rowData[] = point;

        for (int col = 0; col < variables.size(); col++) {
            int index = getVariableNodes().indexOf(variables.get(col));
            double value = rowData[index] + variableMeans[col];

            if (Double.isNaN(value) || Double.isInfinite(value)) {
                throw new IllegalArgumentException("Value out of range: " + value);
            }

            if (isSimulatedPositiveDataOnly() && value < 0) {
                row--;
                continue ROW;
            }

            fullDataSet.setDouble(row, col, value);
        }
    }

    if (latentDataSaved) {
        return fullDataSet;
    } else {
        return DataUtils.restrictToMeasured(fullDataSet);
    }
}

From source file:org.eclipse.january.dataset.Stats.java

/**
 * @param a dataset/*from w  w  w  . j  av  a 2 s. c o m*/
 * @param axis
 * @param ignoreInvalids see {@link Dataset#max(int, boolean...)}
 * @return cumulative sum of items along axis in dataset
 * @since 2.0
 */
public static Dataset cumulativeSum(final Dataset a, int axis, final boolean... ignoreInvalids) {
    axis = a.checkAxis(axis);
    int dtype = a.getDType();
    int[] oshape = a.getShape();
    int alen = oshape[axis];
    oshape[axis] = 1;

    final boolean ignoreNaNs;
    final boolean ignoreInfs;
    if (a.hasFloatingPointElements()) {
        ignoreNaNs = ignoreInvalids != null && ignoreInvalids.length > 0 ? ignoreInvalids[0] : false;
        ignoreInfs = ignoreInvalids != null && ignoreInvalids.length > 1 ? ignoreInvalids[1] : ignoreNaNs;
    } else {
        ignoreNaNs = false;
        ignoreInfs = false;
    }
    Dataset result = DatasetFactory.zeros(a);
    PositionIterator pi = result.getPositionIterator(axis);

    int[] pos = pi.getPos();

    while (pi.hasNext()) {

        if (a.isComplex()) {
            double rv = 0, iv = 0;
            switch (dtype) {
            case Dataset.COMPLEX64:
                ComplexFloatDataset af = (ComplexFloatDataset) a;
                ComplexFloatDataset rf = (ComplexFloatDataset) result;
                for (int j = 0; j < alen; j++) {
                    if (!Double.isNaN(rv) || !Double.isNaN(iv)) {
                        pos[axis] = j;
                        final float r1 = af.getReal(pos);
                        final float i1 = af.getImag(pos);
                        if (ignoreNaNs && (Float.isNaN(r1) || Float.isNaN(i1))) {
                            continue;
                        }
                        if (ignoreInfs && (Float.isInfinite(r1) || Float.isInfinite(i1))) {
                            continue;
                        }
                        rv += r1;
                        iv += i1;
                    }
                    rf.set((float) rv, (float) iv, pos);
                }
                break;
            case Dataset.COMPLEX128:
                ComplexDoubleDataset ad = (ComplexDoubleDataset) a;
                ComplexDoubleDataset rd = (ComplexDoubleDataset) result;
                for (int j = 0; j < alen; j++) {
                    if (!Double.isNaN(rv) || !Double.isNaN(iv)) {
                        pos[axis] = j;
                        final double r1 = ad.getReal(pos);
                        final double i1 = ad.getImag(pos);
                        if (ignoreNaNs && (Double.isNaN(r1) || Double.isNaN(i1))) {
                            continue;
                        }
                        if (ignoreInfs && (Double.isInfinite(r1) || Double.isInfinite(i1))) {
                            continue;
                        }
                        rv += r1;
                        iv += i1;
                    }
                    rd.set(rv, iv, pos);
                }
                break;
            }
        } else {
            final int is;
            final long[] lresults;
            final double[] dresults;

            switch (dtype) {
            case Dataset.BOOL:
            case Dataset.INT8:
            case Dataset.INT16:
            case Dataset.INT32:
            case Dataset.INT64:
                long lresult = 0;
                for (int j = 0; j < alen; j++) {
                    pos[axis] = j;
                    lresult += a.getInt(pos);
                    result.set(lresult, pos);
                }
                break;
            case Dataset.ARRAYINT8:
                is = a.getElementsPerItem();
                lresults = new long[is];
                for (int j = 0; j < alen; j++) {
                    pos[axis] = j;
                    final byte[] va = (byte[]) a.getObject(pos);
                    for (int k = 0; k < is; k++) {
                        lresults[k] += va[k];
                    }
                    result.set(lresults, pos);
                }
                break;
            case Dataset.ARRAYINT16:
                is = a.getElementsPerItem();
                lresults = new long[is];
                for (int j = 0; j < alen; j++) {
                    pos[axis] = j;
                    final short[] va = (short[]) a.getObject(pos);
                    for (int k = 0; k < is; k++) {
                        lresults[k] += va[k];
                    }
                    result.set(lresults, pos);
                }
                break;
            case Dataset.ARRAYINT32:
                is = a.getElementsPerItem();
                lresults = new long[is];
                for (int j = 0; j < alen; j++) {
                    pos[axis] = j;
                    final int[] va = (int[]) a.getObject(pos);
                    for (int k = 0; k < is; k++) {
                        lresults[k] += va[k];
                    }
                    result.set(lresults, pos);
                }
                break;
            case Dataset.ARRAYINT64:
                is = a.getElementsPerItem();
                lresults = new long[is];
                for (int j = 0; j < alen; j++) {
                    pos[axis] = j;
                    final long[] va = (long[]) a.getObject(pos);
                    for (int k = 0; k < is; k++) {
                        lresults[k] += va[k];
                    }
                    result.set(lresults, pos);
                }
                break;
            case Dataset.FLOAT32:
            case Dataset.FLOAT64:
                double dresult = 0.;
                for (int j = 0; j < alen; j++) {
                    if (!Double.isNaN(dresult)) {
                        pos[axis] = j;
                        final double x = a.getDouble(pos);
                        if (ignoreNaNs && Double.isNaN(x)) {
                            continue;
                        }
                        if (ignoreInfs && Double.isInfinite(x)) {
                            continue;
                        }
                        dresult += x;
                    }
                    result.set(dresult, pos);
                }
                break;
            case Dataset.ARRAYFLOAT32:
            case Dataset.ARRAYFLOAT64:
                is = a.getElementsPerItem();
                CompoundDataset da = (CompoundDataset) a;
                double[] dvalues = new double[is];
                dresults = new double[is];
                for (int j = 0; j < alen; j++) {
                    pos[axis] = j;
                    da.getDoubleArray(dvalues, pos);
                    boolean okay = true;
                    for (int k = 0; k < is; k++) {
                        final double val = dvalues[k];
                        if (ignoreNaNs && Double.isNaN(val)) {
                            okay = false;
                            break;
                        }
                        if (ignoreInfs && Double.isInfinite(val)) {
                            okay = false;
                            break;
                        }
                    }
                    if (okay) {
                        for (int k = 0; k < is; k++) {
                            dresults[k] += dvalues[k];
                        }
                    }
                    result.set(dresults, pos);
                }
                break;
            }
        }
    }

    return result;
}

From source file:org.eclipse.january.dataset.AbstractDataset.java

/**
 * Calculate summary statistics for a dataset along an axis
 * @param ignoreNaNs if true, ignore NaNs
 * @param ignoreInfs if true, ignore infinities
 * @param axis/*  w  ww .  j  a  v a2  s  .c  o m*/
 */
protected void calculateSummaryStats(final boolean ignoreNaNs, final boolean ignoreInfs, final int axis) {
    int rank = getRank();

    int[] oshape = getShape();
    int alen = oshape[axis];
    oshape[axis] = 1;

    int[] nshape = new int[rank - 1];
    for (int i = 0; i < axis; i++) {
        nshape[i] = oshape[i];
    }
    for (int i = axis + 1; i < rank; i++) {
        nshape[i - 1] = oshape[i];
    }

    final int dtype = getDType();
    IntegerDataset count = new IntegerDataset(nshape);
    Dataset max = DatasetFactory.zeros(nshape, dtype);
    Dataset min = DatasetFactory.zeros(nshape, dtype);
    IntegerDataset maxIndex = new IntegerDataset(nshape);
    IntegerDataset minIndex = new IntegerDataset(nshape);
    Dataset sum = DatasetFactory.zeros(nshape, DTypeUtils.getLargestDType(dtype));
    DoubleDataset mean = new DoubleDataset(nshape);
    DoubleDataset var = new DoubleDataset(nshape);

    IndexIterator qiter = max.getIterator(true);
    int[] qpos = qiter.getPos();
    int[] spos = oshape.clone();

    while (qiter.hasNext()) {
        int i = 0;
        for (; i < axis; i++) {
            spos[i] = qpos[i];
        }
        spos[i++] = 0;
        for (; i < rank; i++) {
            spos[i] = qpos[i - 1];
        }

        final SummaryStatistics stats = new SummaryStatistics();
        //sum of logs is slow and we dont use it, so blocking its calculation here
        stats.setSumLogImpl(new NullStorelessUnivariateStatistic());

        double amax = Double.NEGATIVE_INFINITY;
        double amin = Double.POSITIVE_INFINITY;
        boolean hasNaNs = false;
        if (ignoreNaNs) {
            for (int j = 0; j < alen; j++) {
                spos[axis] = j;
                final double val = getDouble(spos);

                if (Double.isNaN(val)) {
                    hasNaNs = true;
                    continue;
                } else if (ignoreInfs && Double.isInfinite(val)) {
                    continue;
                }

                if (val > amax) {
                    amax = val;
                }
                if (val < amin) {
                    amin = val;
                }

                stats.addValue(val);
            }
        } else {
            for (int j = 0; j < alen; j++) {
                spos[axis] = j;
                final double val = getDouble(spos);

                if (hasNaNs) {
                    if (!Double.isNaN(val))
                        stats.addValue(0);
                    continue;
                }

                if (Double.isNaN(val)) {
                    amax = Double.NaN;
                    amin = Double.NaN;
                    hasNaNs = true;
                } else if (ignoreInfs && Double.isInfinite(val)) {
                    continue;
                } else {
                    if (val > amax) {
                        amax = val;
                    }
                    if (val < amin) {
                        amin = val;
                    }
                }
                stats.addValue(val);
            }
        }

        count.setAbs(qiter.index, (int) stats.getN());

        max.setObjectAbs(qiter.index, amax);
        min.setObjectAbs(qiter.index, amin);
        boolean fmax = false;
        boolean fmin = false;
        if (hasNaNs) {
            if (ignoreNaNs) {
                for (int j = 0; j < alen; j++) {
                    spos[axis] = j;
                    final double val = getDouble(spos);
                    if (Double.isNaN(val))
                        continue;

                    if (!fmax && val == amax) {
                        maxIndex.setAbs(qiter.index, j);
                        fmax = true;
                        if (fmin)
                            break;
                    }
                    if (!fmin && val == amin) {
                        minIndex.setAbs(qiter.index, j);
                        fmin = true;
                        if (fmax)
                            break;
                    }
                }
            } else {
                for (int j = 0; j < alen; j++) {
                    spos[axis] = j;
                    final double val = getDouble(spos);
                    if (Double.isNaN(val)) {
                        maxIndex.setAbs(qiter.index, j);
                        minIndex.setAbs(qiter.index, j);
                        break;
                    }
                }
            }
        } else {
            for (int j = 0; j < alen; j++) {
                spos[axis] = j;
                final double val = getDouble(spos);
                if (!fmax && val == amax) {
                    maxIndex.setAbs(qiter.index, j);
                    fmax = true;
                    if (fmin)
                        break;
                }
                if (!fmin && val == amin) {
                    minIndex.setAbs(qiter.index, j);
                    fmin = true;
                    if (fmax)
                        break;
                }
            }
        }
        sum.setObjectAbs(qiter.index, stats.getSum());
        mean.setAbs(qiter.index, stats.getMean());
        var.setAbs(qiter.index, stats.getVariance());
    }
    setStoredValue(storeName(ignoreNaNs, ignoreInfs, STORE_COUNT + "-" + axis), count);
    storedValues.put(storeName(ignoreNaNs, ignoreInfs, STORE_MAX + "-" + axis), max);
    storedValues.put(storeName(ignoreNaNs, ignoreInfs, STORE_MIN + "-" + axis), min);
    storedValues.put(storeName(ignoreNaNs, ignoreInfs, STORE_SUM + "-" + axis), sum);
    storedValues.put(storeName(ignoreNaNs, ignoreInfs, STORE_MEAN + "-" + axis), mean);
    storedValues.put(storeName(ignoreNaNs, ignoreInfs, STORE_VAR + "-" + axis), var);
    storedValues.put(storeName(ignoreNaNs, ignoreInfs, STORE_MAX + STORE_INDEX + "-" + axis), maxIndex);
    storedValues.put(storeName(ignoreNaNs, ignoreInfs, STORE_MIN + STORE_INDEX + "-" + axis), minIndex);
}

From source file:org.ncic.bioinfo.sparkseq.algorithms.utils.MathUtils.java

/**
 * Compute in a numerical correct way the quantity log10(1-x)
 *
 * Uses the approximation log10(1-x) = log10(1/x - 1) + log10(x) to avoid very quick underflow
 * in 1-x when x is very small/*  w ww .  ja v a  2s  .  com*/
 *
 * @param x a positive double value between 0.0 and 1.0
 * @return an estimate of log10(1-x)
 */
public static double log10OneMinusX(final double x) {
    if (x == 1.0)
        return Double.NEGATIVE_INFINITY;
    else if (x == 0.0)
        return 0.0;
    else {
        final double d = Math.log10(1 / x - 1) + Math.log10(x);
        return Double.isInfinite(d) || d > 0.0 ? 0.0 : d;
    }
}

From source file:de.unijena.bioinf.FragmentationTreeConstruction.computation.FragmentationPatternAnalysis.java

protected FGraph scoreGraph(FGraph graph) {
    // score graph
    final Iterator<Loss> edges = graph.lossIterator();
    final ProcessedInput input = graph.getAnnotationOrThrow(ProcessedInput.class);
    final Scoring scoring = input.getAnnotationOrThrow(Scoring.class);
    final double[] peakScores = scoring.getPeakScores();
    final double[][] peakPairScores = scoring.getPeakPairScores();
    final LossScorer[] lossScorers = this.lossScorers.toArray(new LossScorer[this.lossScorers.size()]);
    final Object[] precomputeds = new Object[lossScorers.length];
    final ScoredFormulaMap map = graph.getAnnotationOrThrow(ScoredFormulaMap.class);
    final FragmentAnnotation<ProcessedPeak> peakAno = graph.getFragmentAnnotationOrThrow(ProcessedPeak.class);
    for (int i = 0; i < precomputeds.length; ++i)
        precomputeds[i] = lossScorers[i].prepare(input);
    while (edges.hasNext()) {
        final Loss loss = edges.next();
        final Fragment u = loss.getSource();
        final Fragment v = loss.getTarget();
        // take score of molecular formula
        double score = map.get(v.getFormula());
        assert !Double.isInfinite(score);
        // add it to score of the peak
        score += peakScores[peakAno.get(v).getIndex()];
        assert !Double.isInfinite(score);
        // add it to the score of the peak pairs
        if (!u.isRoot())
            score += peakPairScores[peakAno.get(u).getIndex()][peakAno.get(v).getIndex()]; // TODO: Umdrehen!
        assert !Double.isInfinite(score);
        // add the score of the loss
        if (!u.isRoot())
            for (int i = 0; i < lossScorers.length; ++i)
                score += lossScorers[i].score(loss, input, precomputeds[i]);
        assert !Double.isInfinite(score);
        loss.setWeight(score);//from ww  w .  j a va  2  s.co m
    }
    if (reduction != null)
        reduction.reduce(graph, Double.NEGATIVE_INFINITY); // TODO: implement lowerbound
    //assert false;
    return graph;
}

From source file:org.broadinstitute.gatk.utils.MathUtils.java

/**
 * Compute in a numerical correct way the quantity log10(1-x)
 *
 * Uses the approximation log10(1-x) = log10(1/x - 1) + log10(x) to avoid very quick underflow
 * in 1-x when x is very small//  w w w  . ja v a 2  s  . c om
 *
 * @param x a positive double value between 0.0 and 1.0
 * @return an estimate of log10(1-x)
 */
@Requires("x >= 0.0 && x <= 1.0")
@Ensures("result <= 0.0")
public static double log10OneMinusX(final double x) {
    if (x == 1.0)
        return Double.NEGATIVE_INFINITY;
    else if (x == 0.0)
        return 0.0;
    else {
        final double d = Math.log10(1 / x - 1) + Math.log10(x);
        return Double.isInfinite(d) || d > 0.0 ? 0.0 : d;
    }
}