sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1605093 - in /sis/branches/JDK8/core/sis-referencing/src: main/java/org/apache/sis/referencing/operation/transform/ test/java/org/apache/sis/referencing/operation/transform/
Date Tue, 24 Jun 2014 14:30:54 GMT
Author: desruisseaux
Date: Tue Jun 24 14:30:54 2014
New Revision: 1605093

URL: http://svn.apache.org/r1605093
Log:
Simplify LogarithmicTransform1D by removing the explicit support of arbitrary logarithm bases.
Instead, for the rare
cases where someone wants a base other than e or 10, we concatenate the natural logarithm
with a linear transform.

Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ExponentialTransform1D.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/LogarithmicTransform1D.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/TransferFunction.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/TransferFunctionTest.java

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ExponentialTransform1D.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ExponentialTransform1D.java?rev=1605093&r1=1605092&r2=1605093&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ExponentialTransform1D.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ExponentialTransform1D.java
[UTF-8] Tue Jun 24 14:30:54 2014
@@ -62,7 +62,7 @@ final class ExponentialTransform1D exten
     /**
      * The base to be raised to a power.
      */
-    protected final double base;
+    final double base;
 
     /**
      * Natural logarithm of {@link #base}, used for {@link #derivative(double)} computation.
@@ -77,7 +77,7 @@ final class ExponentialTransform1D exten
      * is extensively used as a <cite>transfer function</cite> in grid coverages.
Consequently we keep this explicit
      * field for performance reasons.</div>
      */
-    protected final double scale;
+    final double scale;
 
     /**
      * The inverse of this transform. Created only when first needed. Serialized in order
to avoid
@@ -89,9 +89,9 @@ final class ExponentialTransform1D exten
      * Constructs a new exponential transform which is the inverse of the supplied logarithmic
transform.
      */
     ExponentialTransform1D(final LogarithmicTransform1D inverse) {
-        this.base    = inverse.base;
-        this.lnBase  = inverse.lnBase;
-        this.scale   = Math.pow(base, -inverse.offset);
+        this.base    = inverse.getBase();
+        this.lnBase  = inverse.getLogBase();
+        this.scale   = Math.pow(base, -inverse.getOffset());
         this.inverse = inverse;
     }
 
@@ -257,17 +257,17 @@ final class ExponentialTransform1D exten
     final MathTransform concatenateLog(final LogarithmicTransform1D other, final boolean
applyOtherFirst) {
         if (applyOtherFirst) {
             return MathTransforms.concatenate(
-                    PowerTransform1D.create(lnBase / other.lnBase),
-                    LinearTransform1D.create(scale * Math.pow(base, other.offset), 0));
+                    PowerTransform1D.create(lnBase / other.getLogBase()),
+                    LinearTransform1D.create(scale * Math.pow(base, other.getOffset()), 0));
         } else {
-            final double newScale = lnBase / other.lnBase;
+            final double newScale = lnBase / other.getLogBase();
             final double newOffset;
             if (scale > 0) {
-                newOffset = other.log(scale) + other.offset;
+                newOffset = other.log(scale) + other.getOffset();
             } else {
                 // Maybe the Math.log(...) argument will become
                 // positive if we rewrite the equation that way...
-                newOffset = other.log(scale * other.offset * other.lnBase);
+                newOffset = other.log(scale * other.getOffset() * other.getLogBase());
             }
             if (!Double.isNaN(newOffset)) {
                 return LinearTransform1D.create(newScale, newOffset);

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/LogarithmicTransform1D.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/LogarithmicTransform1D.java?rev=1605093&r1=1605092&r2=1605093&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/LogarithmicTransform1D.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/LogarithmicTransform1D.java
[UTF-8] Tue Jun 24 14:30:54 2014
@@ -26,12 +26,13 @@ import org.apache.sis.util.ComparisonMod
 
 /**
  * A one dimensional, logarithmic transform. This transform is the inverse of {@link ExponentialTransform1D}.
- * Input values <var>x</var> are converted into output values <var>y</var>
using the following equation:
+ * The default implementation computes the natural logarithm of input values using {@link
Math#log(double)}.
+ * Subclasses compute alternate logarithms, for example in base 10 computed by {@link Math#log10(double)}.
  *
- * <blockquote><table class="compact" summary="y = offset + log(x)">
- *   <tr><td><var>y</var></td><td> = </td><td>{@linkplain
#offset} + log<sub>{@linkplain #base}</sub>(<var>x</var>)</td></tr>
- *   <tr><td>            </td><td> = </td><td>{@linkplain
#offset} + ln(<var>x</var>) / ln({@linkplain #base})</td></tr>
- * </table></blockquote>
+ * <p>Logarithms in bases other than <var>e</var> or 10 are computed by
concatenating a linear transform,
+ * using the following mathematical identity:</p>
+ *
+ * <blockquote>    log<sub>base</sub>(<var>x</var>) = ln(<var>x</var>)
/ ln(base)    </blockquote>
  *
  * {@section Serialization}
  * Serialized instances of this class are not guaranteed to be compatible with future SIS
versions.
@@ -50,24 +51,9 @@ class LogarithmicTransform1D extends Abs
     private static final long serialVersionUID = 1535101265352133948L;
 
     /**
-     * The logarithm base.
-     */
-    protected final double base;
-
-    /**
-     * Natural logarithm of {@link #base}, used for {@link #derivative(double)} computation.
-     */
-    final double lnBase;
-
-    /**
-     * The offset to add to the logarithm.
-     *
-     * <span class="note"><b>Note:</b> the offset could be handled by a
concatenation with {@link LinearTransform1D}.
-     * instead than an explicit field in this class. However the <var>offset</var>
+ log<sub>base</sub>(<var>x</var>)
-     * formula is extensively used as a <cite>transfer function</cite> in grid
coverages. Consequently we keep this
-     * explicit field for performance reasons.</span>
+     * The unique instance of the natural logarithmic transform.
      */
-    protected final double offset;
+    private static final LogarithmicTransform1D NATURAL = new LogarithmicTransform1D();
 
     /**
      * The inverse of this transform. Created only when first needed. Serialized in order
to avoid
@@ -76,62 +62,78 @@ class LogarithmicTransform1D extends Abs
     private MathTransform1D inverse;
 
     /**
-     * Constructs a new logarithmic transform which is the
-     * inverse of the supplied exponential transform.
+     * Constructs a new logarithmic transform.
      *
-     * @see #create(ExponentialTransform1D)
+     * @see #create(double, double)
      */
-    private LogarithmicTransform1D(final ExponentialTransform1D inverse) {
-        this.base    = inverse.base;
-        this.lnBase  = inverse.lnBase;
-        this.offset  = -Math.log(inverse.scale) / lnBase;
-        this.inverse = inverse;
+    LogarithmicTransform1D() {
     }
 
     /**
-     * Constructs a new logarithmic transform. This constructor is provided for subclasses
only.
-     * Instances should be created using the {@linkplain #create(double, double) factory
method},
-     * which may return optimized implementations for some particular argument values.
-     *
-     * @param base    The base of the logarithm (typically 10).
-     * @param offset  The offset to add to the logarithm.
-     */
-    protected LogarithmicTransform1D(final double base, final double offset) {
-        ArgumentChecks.ensureStrictlyPositive("base", base);
-        this.base    = base;
-        this.offset  = offset;
-        this.lnBase  = Math.log(base);
-    }
-
-    /**
-     * Constructs a new logarithmic transform which include the given offset after the logarithm.
+     * Constructs a new logarithmic transform which add the given offset after the logarithm.
      *
      * @param  base    The base of the logarithm (typically 10).
      * @param  offset  The offset to add to the logarithm.
      * @return The math transform.
      */
     public static MathTransform1D create(final double base, final double offset) {
+        ArgumentChecks.ensureStrictlyPositive("base", base);
         if (base == 10) {
-            return (offset == 0) ? Base10.INSTANCE : new Base10(offset);
+            return Base10.create(offset);
         }
-        if (base == 0 || base == Double.POSITIVE_INFINITY) {
-            /*
-             * offset + ln(x) / ln(0)   =   offset + ln(x) / -∞   =   offset + -0   for
0 < x < ∞
-             * offset + ln(x) / ln(∞)   =   offset + ln(x) / +∞   =   offset +  0   for
0 < x < ∞
-             */
-            return LinearTransform1D.create(0, offset);
-        }
-        return new LogarithmicTransform1D(base, offset);
+        return NATURAL.concatenate(1 / Math.log(base), offset);
     }
 
     /**
      * Constructs a new logarithmic transform which is the inverse of the supplied exponential
transform.
      */
-    static LogarithmicTransform1D create(final ExponentialTransform1D inverse) {
+    static MathTransform1D create(final ExponentialTransform1D inverse) {
         if (inverse.base == 10) {
-            return new Base10(inverse);
+            return Base10.create(-Math.log10(inverse.scale));
+        } else {
+            return NATURAL.concatenate(1 / inverse.lnBase, -Math.log(inverse.scale) / inverse.lnBase);
         }
-        return new LogarithmicTransform1D(inverse);
+    }
+
+    /**
+     * Returns the concatenation of this transform by the given scale and offset.
+     * This method does not check if a simplification is possible.
+     */
+    private MathTransform1D concatenate(final double scale, final double offset) {
+        final LinearTransform1D t = LinearTransform1D.create(scale, offset);
+        return t.isIdentity() ? this : new ConcatenatedTransformDirect1D(this, t);
+    }
+
+    /**
+     * Concatenates in an optimized way a {@link MathTransform} {@code other} to this
+     * {@code MathTransform}. This implementation can optimize some concatenation with
+     * {@link LinearTransform1D} and {@link ExponentialTransform1D}.
+     *
+     * @param  other The math transform to apply.
+     * @param  applyOtherFirst {@code true} if the transformation order is {@code other}
+     *         followed by {@code this}, or {@code false} if the transformation order is
+     *         {@code this} followed by {@code other}.
+     * @return The combined math transform, or {@code null} if no optimized combined
+     *         transform is available.
+     */
+    @Override
+    final MathTransform concatenate(final MathTransform other, final boolean applyOtherFirst)
{
+        if (other instanceof LinearTransform1D) {
+            final LinearTransform1D linear = (LinearTransform1D) other;
+            if (applyOtherFirst) {
+                if (linear.offset == 0 && linear.scale > 0) {
+                    return create(getBase(), Math.log(linear.scale) / getLogBase() + getOffset());
+                }
+            } else {
+                final double newBase = Math.pow(getBase(), 1 / linear.scale);
+                if (!Double.isNaN(newBase)) {
+                    return create(newBase, linear.scale * getOffset() + linear.offset);
+                }
+            }
+        } else if (other instanceof ExponentialTransform1D) {
+            return ((ExponentialTransform1D) other).concatenateLog(this, !applyOtherFirst);
+        }
+        return super.concatenate(other, applyOtherFirst);
     }
 
     /**
@@ -147,11 +149,33 @@ class LogarithmicTransform1D extends Abs
     }
 
     /**
+     * Returns the base of this logarithmic function.
+     */
+    double getBase() {
+        return Math.E;
+    }
+
+    /**
+     * Returns the natural logarithm of the base of this logarithmic function.
+     * More specifically, returns <code>{@linkplain Math#log(double) Math.log}({@linkplain
#getBase()})</code>.
+     */
+    double getLogBase() {
+        return 1;
+    }
+
+    /**
+     * Returns the offset applied after this logarithmic function.
+     */
+    double getOffset() {
+        return 0;
+    }
+
+    /**
      * Gets the derivative of this function at a value.
      */
     @Override
     public double derivative(final double value) {
-        return 1 / (lnBase * value);
+        return 1 / value;
     }
 
     /**
@@ -162,7 +186,7 @@ class LogarithmicTransform1D extends Abs
      * @return The log of the given value in the base used by this transform.
      */
     double log(final double value) {
-        return Math.log(value) / lnBase;
+        return Math.log(value);
     }
 
     /**
@@ -170,7 +194,7 @@ class LogarithmicTransform1D extends Abs
      */
     @Override
     public double transform(final double value) {
-        return Math.log(value) / lnBase + offset;
+        return Math.log(value);
     }
 
     /**
@@ -180,13 +204,13 @@ class LogarithmicTransform1D extends Abs
     public void transform(final double[] srcPts, int srcOff, final double[] dstPts, int dstOff,
int numPts) {
         if (srcPts != dstPts || srcOff >= dstOff) {
             while (--numPts >= 0) {
-                dstPts[dstOff++] = Math.log(srcPts[srcOff++]) / lnBase + offset;
+                dstPts[dstOff++] = Math.log(srcPts[srcOff++]);
             }
         } else {
             srcOff += numPts;
             dstOff += numPts;
             while (--numPts >= 0) {
-                dstPts[--dstOff] = Math.log(srcPts[--srcOff]) / lnBase + offset;
+                dstPts[--dstOff] = Math.log(srcPts[--srcOff]);
             }
         }
     }
@@ -198,13 +222,13 @@ class LogarithmicTransform1D extends Abs
     public void transform(final float[] srcPts, int srcOff, final float[] dstPts, int dstOff,
int numPts) {
         if (srcPts != dstPts || srcOff >= dstOff) {
             while (--numPts >= 0) {
-                dstPts[dstOff++] = (float) (Math.log(srcPts[srcOff++]) / lnBase + offset);
+                dstPts[dstOff++] = (float) Math.log(srcPts[srcOff++]);
             }
         } else {
             srcOff += numPts;
             dstOff += numPts;
             while (--numPts >= 0) {
-                dstPts[--dstOff] = (float) (Math.log(srcPts[--srcOff]) / lnBase + offset);
+                dstPts[--dstOff] = (float) Math.log(srcPts[--srcOff]);
             }
         }
     }
@@ -215,7 +239,7 @@ class LogarithmicTransform1D extends Abs
     @Override
     public void transform(final double[] srcPts, int srcOff, final float[] dstPts, int dstOff,
int numPts) {
         while (--numPts >= 0) {
-            dstPts[dstOff++] = (float) (Math.log(srcPts[srcOff++]) / lnBase + offset);
+            dstPts[dstOff++] = (float) Math.log(srcPts[srcOff++]);
         }
     }
 
@@ -225,28 +249,77 @@ class LogarithmicTransform1D extends Abs
     @Override
     public void transform(final float[] srcPts, int srcOff, final double[] dstPts, int dstOff,
int numPts) {
         while (--numPts >= 0) {
-            dstPts[dstOff++] = Math.log(srcPts[srcOff++]) / lnBase + offset;
+            dstPts[dstOff++] = Math.log(srcPts[srcOff++]);
         }
     }
 
     /**
      * Special case for base 10 taking advantage of extra precision provided by {@link Math#log10(double)}.
      */
-    private static final class Base10 extends LogarithmicTransform1D {
-        /** For cross-version compatibility. */
+    static final class Base10 extends LogarithmicTransform1D {
+        /**
+         * For cross-version compatibility.
+         */
         private static final long serialVersionUID = -5435804027536647558L;
 
-        /** Commonly used instance. */
-        static LogarithmicTransform1D INSTANCE = new Base10(0);
+        /**
+         * The natural logarithm of 10.
+         */
+        private static final double LOG_10 = 2.302585092994045684;
+
+        /**
+         * Commonly used instance with no offset.
+         */
+        static final Base10 INSTANCE = new Base10(0);
+
+        /**
+         * The offset to add to the logarithm.
+         *
+         * <span class="note"><b>Note:</b> the offset could be handled
by a concatenation with {@link LinearTransform1D}.
+         * instead than an explicit field in this class. However the <var>offset</var>
+ log<sub>base</sub>(<var>x</var>)
+         * formula is extensively used as a <cite>transfer function</cite> in
grid coverages. Consequently we keep this
+         * explicit field for performance reasons.</span>
+         */
+        private final double offset;
+
+        /**
+         * Creates a new instance with the given offset.
+         *
+         * @see #create(double)
+         */
+        private Base10(final double offset) {
+            this.offset = offset;
+        }
+
+        /**
+         * Creates a new instance with the given offset.
+         */
+        public static Base10 create(final double offset) {
+            return (offset == 0) ? INSTANCE : new Base10(offset);
+        }
 
-        /** Constructs the inverse of the supplied exponential transform. */
-        Base10(final ExponentialTransform1D inverse) {
-            super(inverse);
+        /** {@inheritDoc} */
+        @Override
+        double getBase() {
+            return 10;
         }
 
-        /** Creates a new instance with the given offset. */
-        protected Base10(final double offset) {
-            super(10, offset);
+        /** {@inheritDoc} */
+        @Override
+        double getLogBase() {
+            return LOG_10;
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        double getOffset() {
+            return offset;
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public double derivative(final double value) {
+            return (1 / LOG_10) / value;
         }
 
         /** {@inheritDoc} */
@@ -308,62 +381,23 @@ class LogarithmicTransform1D extends Abs
                 dstPts[dstOff++] = Math.log10(srcPts[srcOff++]) + offset;
             }
         }
-    }
 
-    /**
-     * Concatenates in an optimized way a {@link MathTransform} {@code other} to this
-     * {@code MathTransform}. This implementation can optimize some concatenation with
-     * {@link LinearTransform1D} and {@link ExponentialTransform1D}.
-     *
-     * @param  other The math transform to apply.
-     * @param  applyOtherFirst {@code true} if the transformation order is {@code other}
-     *         followed by {@code this}, or {@code false} if the transformation order is
-     *         {@code this} followed by {@code other}.
-     * @return The combined math transform, or {@code null} if no optimized combined
-     *         transform is available.
-     */
-    @Override
-    final MathTransform concatenate(final MathTransform other, final boolean applyOtherFirst)
{
-        if (other instanceof LinearTransform) {
-            final LinearTransform1D linear = (LinearTransform1D) other;
-            if (applyOtherFirst) {
-                if (linear.offset == 0 && linear.scale > 0) {
-                    return create(base, Math.log(linear.scale) / lnBase + offset);
-                }
-            } else {
-                final double newBase = Math.pow(base, 1 / linear.scale);
-                if (!Double.isNaN(newBase)) {
-                    return create(newBase, linear.scale * offset + linear.offset);
-                }
-            }
-        } else if (other instanceof ExponentialTransform1D) {
-            return ((ExponentialTransform1D) other).concatenateLog(this, !applyOtherFirst);
+        /** {@inheritDoc} */
+        @Override
+        protected int computeHashCode() {
+            return Numerics.hashCode(Double.doubleToLongBits(offset)) ^ super.computeHashCode();
         }
-        return super.concatenate(other, applyOtherFirst);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    protected int computeHashCode() {
-        return Numerics.hashCode(Double.doubleToLongBits(base) +
-                            31 * Double.doubleToLongBits(offset)) ^ super.computeHashCode();
-    }
 
-    /**
-     * Compares the specified object with this math transform for equality.
-     */
-    @Override
-    public boolean equals(final Object object, final ComparisonMode mode) {
-        if (object == this) {
-            return true;  // Optimization for a common case.
-        }
-        if (super.equals(object, mode)) {
-            final LogarithmicTransform1D that = (LogarithmicTransform1D) object;
-            return Numerics.equals(this.base,   that.base) &&
-                   Numerics.equals(this.offset, that.offset);
+        /** Compares the specified object with this math transform for equality. */
+        @Override
+        public boolean equals(final Object object, final ComparisonMode mode) {
+            if (object == this) {
+                return true;  // Optimization for a common case.
+            }
+            if (super.equals(object, mode)) {
+                return Numerics.equals(offset, ((Base10) object).offset);
+            }
+            return false;
         }
-        return false;
     }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/TransferFunction.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/TransferFunction.java?rev=1605093&r1=1605092&r2=1605093&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/TransferFunction.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/TransferFunction.java
[UTF-8] Tue Jun 24 14:30:54 2014
@@ -246,11 +246,31 @@ public class TransferFunction implements
         } else if (function instanceof LogarithmicTransform1D) {
             final LogarithmicTransform1D f = (LogarithmicTransform1D) function;
             type   = TransferFunctionType.LOGARITHMIC;
-            base   = f.base;
-            offset = f.offset;
+            base   = f.getBase();
+            offset = f.getOffset();
             scale  = 1;
         } else {
-            throw new IllegalArgumentException(Errors.format(Errors.Keys.UnknownType_1, function.getClass()));
+            /*
+             * If we did not recognized one of the known types, maybe the given function
+             * is the result of some concatenation. Try to concatenate a logarithmic or
+             * exponential transform and see if the result is linear.
+             */
+            final LogarithmicTransform1D log = LogarithmicTransform1D.Base10.INSTANCE;
+            MathTransform1D f = MathTransforms.concatenate(function, log);
+            if (f instanceof LinearTransform) {
+                setLinearTerms((LinearTransform) f);
+                type = TransferFunctionType.EXPONENTIAL;
+                base = 10;
+            } else {
+                f = MathTransforms.concatenate(log.inverse(), function);
+                if (f instanceof LinearTransform) {
+                    setLinearTerms((LinearTransform) f);
+                    type = TransferFunctionType.LOGARITHMIC;
+                    base = 10;
+                } else {
+                    throw new IllegalArgumentException(Errors.format(Errors.Keys.UnknownType_1,
function.getClass()));
+                }
+            }
         }
         transform = function;
     }
@@ -287,7 +307,7 @@ public class TransferFunction implements
             if (scale == -1) {
                 b.append('−');
             } else {
-                StringBuilders.trimFractionalPart(b.append(scale).append('∙'));
+                StringBuilders.trimFractionalPart(b.append(scale).append('⋅'));
             }
         }
         if (TransferFunctionType.LINEAR.equals(type)) {

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/TransferFunctionTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/TransferFunctionTest.java?rev=1605093&r1=1605092&r2=1605093&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/TransferFunctionTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/TransferFunctionTest.java
[UTF-8] Tue Jun 24 14:30:54 2014
@@ -56,7 +56,7 @@ public final class TransferFunctionTest 
 
         f.setScale(0.15);
         f.setOffset(-2);
-        assertEquals("toString", "y = 0.15∙x − 2", f.toString());
+        assertEquals("toString", "y = 0.15⋅x − 2", f.toString());
         final MathTransform1D transform = f.getTransform();
         assertInstanceOf("transform", LinearTransform.class, transform);
         assertMatrixEquals("transform.matrix", new Matrix2(0.15, -2, 0, 1),
@@ -106,7 +106,7 @@ public final class TransferFunctionTest 
         f.setType(TransferFunctionType.EXPONENTIAL);
         f.setScale(0.15);
         assertEquals("base", 10, f.getBase(), STRICT);
-        assertEquals("toString", "y = 0.15∙10ˣ", f.toString());
+        assertEquals("toString", "y = 0.15⋅10ˣ", f.toString());
         final MathTransform1D transform = f.getTransform();
         assertInstanceOf("transform", ExponentialTransform1D.class, transform);
         /*
@@ -119,4 +119,28 @@ public final class TransferFunctionTest 
         assertEquals("scale",   0.15, b.getScale(),  STRICT);
         assertEquals("offset",  0,    b.getOffset(), STRICT);
     }
+
+    /**
+     * Tests the creation of a concatenated transfer function.
+     */
+    @Test
+    @DependsOnMethod("testLogarithmic")
+    public void testConcatenated() {
+        final TransferFunction f = new TransferFunction();
+        f.setType(TransferFunctionType.LOGARITHMIC);
+        f.setScale(0.15);
+        f.setOffset(-2);
+        assertEquals("toString", "y = 0.15⋅㏒⒳ − 2", f.toString());
+        final MathTransform1D transform = f.getTransform();
+        assertInstanceOf("transform", ConcatenatedTransformDirect1D.class, transform);
+        /*
+         * Get back the coefficients.
+         */
+        final TransferFunction b = new TransferFunction();
+        b.setTransform(transform);
+        assertEquals("type", TransferFunctionType.LOGARITHMIC, b.getType());
+        assertEquals("base",   10,    b.getBase(),   STRICT);
+        assertEquals("scale",   0.15, b.getScale(),  1E-16);
+        assertEquals("offset", -2,    b.getOffset(), 1E-16);
+    }
 }



Mime
View raw message