Package org.apache.sis.internal.util

Examples of org.apache.sis.internal.util.DoubleDouble

{@code DoubleDouble} is used as an alternative to {@link java.math.BigDecimal} when we do not need arbitraryprecision, we do not want to convert from base 2 to base 10, we need support for NaN and infinities, we want more compact storage and better performance. {@code DoubleDouble} can be converted to {@code BigDecimal} asbelow: {@preformat javaBigDecimal decimal = new BigDecimal(dd.value).add(new BigDecimal(dd.error));}We do not provide convenience method for the above in order to avoid dependency to {@code BigDecimal}. {@section Impact of availability of FMA instructions}If fused multiply-add (FMA) instruction are available in a future Java version (see SIS-136 on Apache SIS JIRA), then the following methods should be revisited: @author Martin Desruisseaux (Geomatys) @since 0.4 @version 0.4 @module @see Wikipedia: Double-double arithmetic

    @Override
    final DoubleDouble period(final Date time) {
        if (time != null) {
            final long millis = time.getTime() - timeReference;
            if (millis != 0) { // Returns null for 0 as an optimization.
                final DoubleDouble period = new DoubleDouble(millis, 0);
                period.divide(1000 * JULIAN_YEAR_LENGTH, 0);
                return period;
            }
        }
        return null;
    }
View Full Code Here


     * @param index  0 for {@code tX}, 1 for {@code tY}, <i>etc.</i> in {@code TOWGS84[]} order.
     * @param period The value computed by {@link #period(Date)}, or {@code null}.
     */
    @Override
    final DoubleDouble param(final int index, final DoubleDouble period) {
        final DoubleDouble p = super.param(index, period);
        if (period != null) {
            final double value = period.value;
            final double error = period.error;
            final double d;
            switch (index) {
                case 0: d = dtX; break;
                case 1: d = dtY; break;
                case 2: d = dtZ; break;
                case 3: d = drX; break;
                case 4: d = drY; break;
                case 5: d = drZ; break;
                case 6: d = ddS; period.multiply(1000, 0); break;
                default: throw new AssertionError(index);
            }
            period.multiply(d);
            p.add(period);
            period.value = value;
            period.error = error;
        }
        return p;
    }
View Full Code Here

         * Double.MIN_VALUE in order to differentiate them from automatically calculated
         * error terms. The result shall use double-double arithmetic, and we should be
         * able to find back our error terms.
         */
        for (int i = 0; i < elements.length; i += SIZE+1) {
            elements[i] = new DoubleDouble(elements[i].doubleValue(), SENTINEL_VALUE);
        }
        final MatrixSIS matrix = Matrices.create(SIZE, SIZE, elements);
        assertInstanceOf("Created with DoubleDouble elements", GeneralMatrix.class, matrix);
        assertFalse(expected.equals(matrix)); // Because not the same type.
        assertTrue(Matrices.equals(expected, matrix, ComparisonMode.BY_CONTRACT));
View Full Code Here

        final int[] pivot = new int[size];
        for (int j=0; j<size; j++) {
           pivot[j] = j;
        }
        final double[]  column = new double[size * 2]; // [0 … size-1] : column values; [size … 2*size-1] : error terms.
        final DoubleDouble acc = new DoubleDouble();   // Temporary variable for sum ("accumulator") and subtraction.
        final DoubleDouble rat = new DoubleDouble();   // Temporary variable for products and ratios.
        for (int i=0; i<size; i++) {
            /*
             * Make a copy of the i-th column.
             */
            for (int j=0; j<size; j++) {
                final int k = j*size + i;
                column[j]        = LU[k];            // Value
                column[j + size] = LU[k + errorLU]// Error
            }
            /*
             * Apply previous transformations. This part is equivalent to the following code,
             * but using double-double arithmetic instead than the primitive 'double' type:
             *
             *     double sum = 0;
             *     for (int k=0; k<kmax; k++) {
             *         sum += LU[rowOffset + k] * column[k];
             *     }
             *     LU[rowOffset + i] = (column[j] -= sum);
             */
            for (int j=0; j<size; j++) {
                final int rowOffset = j*size;
                final int kmax = Math.min(j,i);
                acc.clear();
                for (int k=0; k<kmax; k++) {
                    rat.setFrom(LU, rowOffset + k, errorLU);
                    rat.multiply(column, k, size);
                    acc.add(rat);
                }
                acc.subtract(column, j, size);
                acc.negate();
                acc.storeTo(column, j, size);
                acc.storeTo(LU, rowOffset + i, errorLU);
            }
            /*
             * Find pivot and exchange if necessary. There is no floating-point arithmetic here
             * (ignoring the comparison for magnitude order), only work on index values.
             */
            int p = i;
            for (int j=i; ++j < size;) {
                if (Math.abs(column[j]) > Math.abs(column[p])) {
                    p = j;
                }
            }
            if (p != i) {
                final int pRow = p*size;
                final int iRow = i*size;
                for (int k=0; k<size; k++) { // Swap two full rows.
                    DoubleDouble.swap(LU, pRow + k, iRow + k, errorLU);
                }
                ArraysExt.swap(pivot, p, i);
            }
            /*
             * Compute multipliers. This part is equivalent to the following code, but
             * using double-double arithmetic instead than the primitive 'double' type:
             *
             *     final double sum = LU[i*size + i];
             *     if (sum != 0.0) {
             *         for (int j=i; ++j < size;) {
             *             LU[j*size + i] /= sum;
             *         }
             *     }
             */
            acc.setFrom(LU, i*size + i, errorLU);
            if (!acc.isZero()) {
                for (int j=i; ++j < size;) {
                    final int t = j*size + i;
                    rat.setFrom(acc);
                    rat.inverseDivide(LU, t, errorLU);
                    rat.storeTo      (LU, t, errorLU);
                }
            }
        }
        /*
         * At this point, we are done computing LU.
         * Ensure that the matrix is not singular.
         */
        for (int j=0; j<size; j++) {
            rat.setFrom(LU, j*size + j, errorLU);
            if (rat.isZero()) {
                throw new NoninvertibleMatrixException(Errors.format(Errors.Keys.SingularMatrix));
            }
        }
        /*
         * Copy right hand side with pivoting. Write the result directly in the elements array
         * of the result matrix. This block does not perform floating-point arithmetic operations.
         */
        final GeneralMatrix result = GeneralMatrix.createExtendedPrecision(size, innerSize);
        final double[] elements = result.elements;
        final int errorOffset = size * innerSize;
        for (int k=0,j=0; j<size; j++) {
            final int p = pivot[j];
            for (int i=0; i<innerSize; i++) {
                if (eltY != null) {
                    final int t = p*innerSize + i;
                    elements[k]               = eltY[t];
                    elements[k + errorOffset] = eltY[t + errorOffset];
                } else {
                    elements[k] = Y.getElement(p, i);
                }
                k++;
            }
        }
        /*
         * Solve L*Y = B(pivot, :). The inner block is equivalent to the following line,
         * but using double-double arithmetic instead of 'double' primitive type:
         *
         *     elements[loRowOffset + i] -= (elements[rowOffset + i] * LU[luRowOffset + k]);
         */
        for (int k=0; k<size; k++) {
            final int rowOffset = k*innerSize;          // Offset of row computed by current iteration.
            for (int j=k; ++j < size;) {
                final int loRowOffset = j*innerSize;    // Offset of some row after the current row.
                final int luRowOffset = j*size;         // Offset of the corresponding row in the LU matrix.
                for (int i=0; i<innerSize; i++) {
                    acc.setFrom (elements, loRowOffset + i, errorOffset);
                    rat.setFrom (elements, rowOffset   + i, errorOffset);
                    rat.multiply(LU,       luRowOffset + k, errorLU);
                    acc.subtract(rat);
                    acc.storeTo (elements, loRowOffset + i, errorOffset);
                }
            }
        }
        /*
         * Solve U*X = Y. The content of the loop is equivalent to the following line,
         * but using double-double arithmetic instead of 'double' primitive type:
         *
         *     double sum = LU[k*size + k];
         *     for (int i=0; i<innerSize; i++) {
         *         elements[rowOffset + i] /= sum;
         *     }
         *     for (int j=0; j<k; j++) {
         *         sum = LU[j*size + k];
         *         for (int i=0; i<innerSize; i++) {
         *             elements[upRowOffset + i] -= (elements[rowOffset + i] * sum);
         *         }
         *     }
         */
        for (int k=size; --k >= 0;) {
            final int rowOffset = k*innerSize;          // Offset of row computed by current iteration.
            acc.setFrom(LU, k*size + k, errorLU);       // A diagonal element on the current row.
            for (int i=0; i<innerSize; i++) {           // Apply to all columns in the current row.
                rat.setFrom(acc);
                rat.inverseDivide(elements, rowOffset + i, errorOffset);
                rat.storeTo      (elements, rowOffset + i, errorOffset);
            }
            for (int j=0; j<k; j++) {
                final int upRowOffset = j*innerSize;    // Offset of a row before (locate upper) the current row.
                acc.setFrom(LU, j*size + k, errorLU);   // Same column than the diagonal element, but in the upper row.
                for (int i=0; i<innerSize; i++) {       // Apply to all columns in the upper row.
                    rat.setFrom(elements, rowOffset + i, errorOffset);
                    rat.multiply(acc);
                    rat.subtract(elements, upRowOffset + i, errorOffset);
                    rat.negate();
                    rat.storeTo(elements, upRowOffset + i, errorOffset);
                }
            }
        }
        return result;
    }
View Full Code Here

        if (row >= 0 && row < numRow && column >= 0 && column < numCol) {
            int i = row * numCol + column;
            final double value = elements[i];
            i += numRow * numCol;
            if (i < elements.length) {
                return new DoubleDouble(value, elements[i]);
            } else {
                return value;
            }
        } else {
            throw indexOutOfBounds(row, column);
View Full Code Here

    public final void normalizeColumns() {
        final int numRow = this.numRow; // Protection against accidental changes.
        final int numCol = this.numCol;
        final int errors = numRow * numCol; // Where error values start.
        final double[] elt = getExtendedElements(this, numRow, numCol, false);
        final DoubleDouble sum = new DoubleDouble();
        final DoubleDouble dot = new DoubleDouble();
        for (int i=0; i<numCol; i++) {
            sum.clear();
            for (int j=0; j<numRow; j++) {
                dot.setFrom(elt, j*numCol + i, errors);
                dot.multiply(dot);
                sum.add(dot);
            }
            sum.sqrt();
            for (int j=0; j<numRow; j++) {
                final int k = j*numCol + i;
                dot.setFrom(sum);
                dot.inverseDivide(elt, k, errors);
                dot.storeTo(elt, k, errors);
            }
        }
        if (elt != elements) {
            System.arraycopy(elt, 0, elements, 0, elements.length);
        }
View Full Code Here

        final int errA        = numRow * nc;
        final int errB        = nc * numCol;
        /*
         * Compute the product, to be stored directly in 'this'.
         */
        final DoubleDouble dot = new DoubleDouble();
        final DoubleDouble sum = new DoubleDouble();
        for (int k=0,j=0; j<numRow; j++) {
            for (int i=0; i<numCol; i++) {
                sum.clear();
                double max = 0;
                int iB = i;       // Index of values in a single column of B.
                int iA = j * nc;  // Index of values in a single row of A.
                final int nextRow = iA + nc;
                while (iA < nextRow) {
                    dot.setFrom (eltA, iA, errA);
                    dot.multiply(eltB, iB, errB);
                    sum.add(dot);
                    iB += numCol; // Move to next row of B.
                    iA++;         // Move to next column of A.
                    final double value = Math.abs(dot.value);
                    if (value > max) max = value;
                }
                if (Math.abs(sum.value) < Math.ulp(max) * ZERO_THRESHOLD) {
                    sum.clear(); // Sum is not significant according double arithmetic.
                }
                sum.storeTo(elements, k++, errorOffset);
            }
        }
    }
View Full Code Here

            case 4: p = rY; break;
            case 5: p = rZ; break;
            case 6: p = dS; break;
            default: throw new AssertionError(index);
        }
        return new DoubleDouble(p);
    }
View Full Code Here

     * @return An affine transform in geocentric space created from this Bursa-Wolf parameters and the given time.
     *
     * @see DefaultGeodeticDatum#getPositionVectorTransformation(GeodeticDatum, Extent)
     */
    public Matrix getPositionVectorTransformation(final Date time) {
        final DoubleDouble period = period(time);
        if (period == null && isTranslation()) {
            final Matrix4 matrix = new Matrix4();
            matrix.m03 = tX;
            matrix.m13 = tY;
            matrix.m23 = tZ;
            return matrix;
        }
        /*
         * Above was an optimization for the common case where the Bursa-Wolf parameters contain only
         * translation terms. If we have rotation or scale terms, then use double-double arithmetic.
         */
        final DoubleDouble RS = DoubleDouble.createSecondsToRadians();
        final DoubleDouble S = param(6, period);
        S.divide(PPM, 0);
        S.add(1, 0);        // S = 1 + dS / PPM;
        RS.multiply(S);     // RS = toRadians(1″) * S;
        final DoubleDouble  X = param(3, period); X.multiply(RS);
        final DoubleDouble  Y = param(4, period); Y.multiply(RS);
        final DoubleDouble  Z = param(5, period); Z.multiply(RS);
        final DoubleDouble mX = new DoubleDouble(X); mX.negate();
        final DoubleDouble mY = new DoubleDouble(Y); mY.negate();
        final DoubleDouble mZ = new DoubleDouble(Z); mZ.negate();
        final Integer       O = 0; // Fetch Integer instance only once.
        return Matrices.create(4, 4, new Number[] {
                 S,  mZ,   Y,  param(0, period),
                 Z,   S,  mX,  param(1, period),
                mY,   X,   S,  param(2, period),
View Full Code Here

        /*
         * Scale factor: take the average of elements on the diagonal. All those
         * elements should have the same value, but we tolerate slight deviation
         * (this will be verified later).
         */
        final DoubleDouble S = new DoubleDouble(getNumber(matrix, 0,0));
        S.add(getNumber(matrix, 1,1));
        S.add(getNumber(matrix, 2,2));
        S.divide(3, 0);
        /*
         * Computes: RS = S * toRadians(1″)
         *           dS = (S-1) * PPM
         */
        final DoubleDouble RS = DoubleDouble.createSecondsToRadians();
        RS.multiply(S);
        S.add(-1, 0);
        S.multiply(PPM, 0);
        dS = S.value;
        /*
         * Rotation terms. Each rotation terms appear twice, with one value being the negative of the other value.
View Full Code Here

TOP

Related Classes of org.apache.sis.internal.util.DoubleDouble

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.