Author: desruisseaux
Date: Mon Oct 17 15:57:29 2016
New Revision: 1765320

URL: http://svn.apache.org/viewvc?rev=1765320&view=rev
Log:
Finish implementation of all Unit methods. Not yet tested (tests will be the 
subject of next commit).

Added:
    
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/ConventionalUnit.java
   (with props)
Modified:
    
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/AbstractUnit.java
    
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/ConcatenatedConverter.java
    
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/LinearConverter.java
    
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/SystemUnit.java
    
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/UnitDimension.java
    
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java
    
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
    
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
    
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties

Modified: 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/AbstractUnit.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/AbstractUnit.java?rev=1765320&r1=1765319&r2=1765320&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/AbstractUnit.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/AbstractUnit.java
 [UTF-8] Mon Oct 17 15:57:29 2016
@@ -16,17 +16,16 @@
  */
 package org.apache.sis.measure;
 
-import java.io.Serializable;
 import java.util.Objects;
+import java.io.Serializable;
 import javax.measure.Unit;
 import javax.measure.Quantity;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.resources.Errors;
-import org.apache.sis.util.collection.WeakHashSet;
 
 
 /**
- * Base class of all unit implementations. There is conceptually 5 kinds of 
units,
+ * Base class of all unit implementations. There is conceptually 4 kinds of 
units,
  * but some of them are implemented by the same class:
  *
  * <ul>
@@ -37,10 +36,9 @@ import org.apache.sis.util.collection.We
  *       For example "m/s" is a derived units.</li>
  *   <li><b>Alternate units</b> are dimensionless units handled as if they had 
a dimension.
  *       An example is angular degrees.</li>
- *   <li><b>Scaled units</b> are units multiplied by a constant value compared 
to a base unit.
- *       For example "km" is a scaled unit equals to 1000 metres.</li>
- *   <li><b>Shifted units</b> are units shifted by a constant value compared 
to a base unit.
- *       For example "°C" is a shifted unit equals to a value in degree Kelvin 
minus 273.15.</li>
+ *   <li><b>Conventional units</b> are units multiplied or shifted by a 
constant value compared to a base,
+ *       derived or alternate unit. For example "km" is a unit equals to 1000 
metres, and"°C" is a unit
+ *       shifted by 237.15 degrees compared to the Kelvin unit.</li>
  * </ul>
  *
  * In Apache SIS implementation, base and derived units are represented by the 
same class: {@link SystemUnit}.
@@ -55,10 +53,9 @@ import org.apache.sis.util.collection.We
  */
 abstract class AbstractUnit<Q extends Quantity<Q>> implements Unit<Q>, 
Serializable {
     /**
-     * Pool of all {@code AbstractUnit} instances created up to date.
+     * For cross-version compatibility.
      */
-    @SuppressWarnings("rawtypes")
-    private static final WeakHashSet<AbstractUnit> POOL = new 
WeakHashSet<>(AbstractUnit.class);
+    private static final long serialVersionUID = -5559950920796714303L;
 
     /**
      * The unit symbol, or {@code null} if this unit has no specific symbol. 
If {@code null},
@@ -157,109 +154,79 @@ abstract class AbstractUnit<Q extends Qu
     }
 
     /**
-     * Casts this unit to a parameterized unit of specified nature or throw a 
{@code ClassCastException}
-     * if the dimension of the specified quantity and this unit's dimension do 
not match.
+     * Returns the error message for an incompatible unit.
+     */
+    final String incompatible(final Unit<?> that) {
+        return Errors.format(Errors.Keys.IncompatibleUnits_2, this, that);
+    }
+
+    /**
+     * Returns the result of setting the origin of the scale of measurement to 
the given value.
+     * For example {@code CELSIUS = KELVIN.shift(273.15)} returns a unit where 
0°C is equals to 273.15 K.
      *
-     * @param  <T>   the type of the quantity measured by the unit.
-     * @param  type  the quantity class identifying the nature of the unit.
-     * @return this unit parameterized with the specified type.
-     * @throws ClassCastException if the dimension of this unit is different 
from the specified quantity dimension.
+     * @param  offset  the value to add when converting from the new unit to 
this unit.
+     * @return this unit offset by the specified value, or {@code this} if the 
given offset is zero.
      */
     @Override
-    @SuppressWarnings("unchecked")
-    public final <T extends Quantity<T>> Unit<T> asType(final Class<T> type) 
throws ClassCastException {
-        ArgumentChecks.ensureNonNull("type", type);
-        final Class<Quantity<Q>> quantity = getSystemUnit().quantity;
-        if (type.equals(quantity)) {
-            return (Unit<T>) this;
-        }
-        throw new 
ClassCastException(Errors.format(Errors.Keys.CanNotConvertFromType_2,
-                "Unit<" + quantity.getSimpleName() + '>', "Unit<" + 
type.getSimpleName() + '>'));
+    public final Unit<Q> shift(final double offset) {
+        return transform(LinearConverter.create(1, offset));
     }
 
     /**
-     * Returns a unique instance of this unit. An initially empty pool of 
{@code AbstractUnit}
-     * instances is maintained. When invoked, this method first checks if an 
instance equals
-     * to this unit exists in the pool. If such instance is found, then it is 
returned.
-     * Otherwise this instance is added in the pool using weak references and 
returned.
+     * Returns the result of multiplying this unit by the specified factor.
+     * For example {@code KILOMETRE = METRE.multiply(1000)} returns a unit 
where 1 km is equals to 1000 m.
+     *
+     * @param  multiplier  the scale factor when converting from the new unit 
to this unit.
+     * @return this unit scaled by the specified multiplier.
      */
-    final AbstractUnit<Q> intern() {
-        return POOL.unique(this);
+    @Override
+    public final Unit<Q> multiply(final double multiplier) {
+        return transform(LinearConverter.create(multiplier, 0));
     }
 
     /**
-     * Returns an instance equals to this unit, ignoring the symbol.
-     * If such instance exists in the pool of existing units, it is
-     * returned. Otherwise this method returns {@code this}.
+     * Returns the result of dividing this unit by an approximate divisor.
+     * For example {@code GRAM = KILOGRAM.divide(1000)} returns a unit where 1 
g is equals to 0.001 kg.
+     *
+     * @param  divisor  the inverse of the scale factor when converting from 
the new unit to this unit.
+     * @return this unit divided by the specified divisor.
      */
-    final AbstractUnit<Q> internIgnoreSymbol() {
-        @SuppressWarnings("unchecked")
-        AbstractUnit<Q> unit = POOL.get(new Unamed(this));
-        if (unit == null) {
-            unit = this;
-        }
-        return unit;
+    @Override
+    public final Unit<Q> divide(final double divisor) {
+        return transform(LinearConverter.create(1/divisor, 0));
     }
 
     /**
-     * Compares this unit with the given unit, ignoring symbol.
-     * Implementations shall check the {@code obj} type.
+     * Returns the inverse of this unit.
      *
-     * @param  obj The object to compare with this unit, or {@code null}.
-     * @return {@code true} If the given unit is equals to this unit, ignoring 
symbol.
+     * @return 1 / {@code this}
      */
-    protected abstract boolean equalsIgnoreSymbol(Object obj);
+    @Override
+    public final Unit<?> inverse() {
+        return pow(-1);
+    }
 
     /**
      * Compares this unit with the given object for equality.
      *
-     * @param  other The other object to compares with this unit, or {@code 
null}.
+     * @param  other  the other object to compares with this unit, or {@code 
null}.
      * @return {@code true} if the given object is equals to this unit.
      */
     @Override
-    public final boolean equals(Object other) {
-        if (other instanceof Unamed) {
-            other = ((Unamed) other).unit;
-        }
-        if (equalsIgnoreSymbol(other)) {
-            return Objects.equals(symbol, ((AbstractUnit<?>) other).symbol);
+    public boolean equals(final Object other) {
+        if (other != null && other.getClass() == getClass()) {
+            final AbstractUnit<?> that = (AbstractUnit<?>) other;
+            return epsg == that.epsg && Objects.equals(symbol, that.symbol) && 
Objects.equals(name, that.name);
         }
         return false;
     }
 
     /**
-     * A temporary proxy used by {@link #internIgnoreSymbol()} for finding an 
existing units,
-     * ignoring the symbol.
-     */
-    private static final class Unamed {
-        final AbstractUnit<?> unit;
-
-        Unamed(final AbstractUnit<?> unit)          {this.unit = unit;}
-        @Override public int hashCode()             {return unit.hashCode();}
-        @Override public boolean equals(Object obj) {return 
unit.equalsIgnoreSymbol(obj);}
-    }
-
-    /**
-     * Returns a hash code value for this unit, ignoring symbol.
+     * Returns a hash code value for this unit.
      */
     @Override
-    public abstract int hashCode();
-
-    /**
-     * Replaces the deserialized unit instance by a unique instance, if any.
-     *
-     * @return The unique unit instance.
-     */
-    protected final Object readResolve() {
-        return intern();
-    }
-
-    /**
-     * Returns the exception to throw when the given unit arguments are illegal
-     * for the operation to perform.
-     */
-    final ArithmeticException illegalUnitOperation(final String operation, 
final AbstractUnit<?> that) {
-        return new ArithmeticException(); // TODO: provide a message.
+    public int hashCode() {
+        return epsg + 31 * Objects.hashCode(symbol);
     }
 
     /**

Modified: 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/ConcatenatedConverter.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/ConcatenatedConverter.java?rev=1765320&r1=1765319&r2=1765320&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/ConcatenatedConverter.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/ConcatenatedConverter.java
 [UTF-8] Mon Oct 17 15:57:29 2016
@@ -20,6 +20,7 @@ import java.util.List;
 import java.util.ArrayList;
 import java.io.Serializable;
 import javax.measure.UnitConverter;
+import org.apache.sis.util.ArgumentChecks;
 
 
 /**
@@ -113,6 +114,10 @@ final class ConcatenatedConverter implem
      */
     @Override
     public UnitConverter concatenate(final UnitConverter converter) {
+        ArgumentChecks.ensureNonNull("converter", converter);
+        if (equals(converter.inverse())) {
+            return LinearConverter.IDENTITY;
+        }
         // Delegate to c1 and c2 because they may provide more intelligent 
'concatenate' implementations.
         return c2.concatenate(c1.concatenate(converter));
     }

Added: 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/ConventionalUnit.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/ConventionalUnit.java?rev=1765320&view=auto
==============================================================================
--- 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/ConventionalUnit.java
 (added)
+++ 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/ConventionalUnit.java
 [UTF-8] Mon Oct 17 15:57:29 2016
@@ -0,0 +1,273 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.measure;
+
+import java.util.Map;
+import javax.measure.Unit;
+import javax.measure.Quantity;
+import javax.measure.Dimension;
+import javax.measure.UnitConverter;
+import javax.measure.UnconvertibleException;
+import javax.measure.IncommensurableException;
+import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.ArgumentChecks;
+
+
+/**
+ * A unit of measure which is related to a base or derived unit through a 
conversion formula.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.8
+ * @version 0.8
+ * @module
+ */
+final class ConventionalUnit<Q extends Quantity<Q>> extends AbstractUnit<Q> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 6963634855104019466L;
+
+    /**
+     * The base, derived or alternate units to which this {@code 
ConventionalUnit} is related.
+     * This is called "preferred unit" in GML.
+     */
+    final SystemUnit<Q> target;
+
+    /**
+     * The conversion from this unit to the {@linkplain #target} unit.
+     */
+    final UnitConverter toTarget;
+
+    /**
+     * Creates a new unit having the given symbol and EPSG code.
+     *
+     * @param  target     the base or derived units to which this {@code 
ConventionalUnit} is related.
+     * @param  toTarget   the conversion from this unit to the {@code target} 
unit.
+     * @param  name       the unit name,   or {@code null} if this unit has no 
specific name.
+     * @param  symbol     the unit symbol, or {@code null} if this unit has no 
specific symbol.
+     * @param  epsg       the EPSG code,   or 0 if this unit has no EPSG code.
+     */
+    ConventionalUnit(final SystemUnit<Q> target, final UnitConverter toTarget,
+            final String name, final String symbol, final short epsg)
+    {
+        super(name, symbol, epsg);
+        this.target   = target;
+        this.toTarget = toTarget;
+    }
+
+    /**
+     * Creates a new unit with default name and symbol for the given converter.
+     */
+    static <Q extends Quantity<Q>> AbstractUnit<Q> create(final SystemUnit<Q> 
target, final UnitConverter toTarget) {
+        if (toTarget.isIdentity()) {
+            return target;
+        }
+        // TODO: check for existing unit.
+        return new ConventionalUnit<>(target, toTarget, null, null, (short) 0);
+    }
+
+    /**
+     * Returns the dimension of this unit.
+     * Two units {@code u1} and {@code u2} are {@linkplain #isCompatible(Unit) 
compatible}
+     * if and only if {@code u1.getDimension().equals(u2.getDimension())}.
+     *
+     * @return the dimension of this unit.
+     *
+     * @see #isCompatible(Unit)
+     */
+    @Override
+    public Dimension getDimension() {
+        return target.dimension;
+    }
+
+    /**
+     * Returns the unscaled system unit from which this unit is derived.
+     */
+    @Override
+    public SystemUnit<Q> getSystemUnit() {
+        return target;
+    }
+
+    /**
+     * Returns the base units and their exponent whose product is the system 
unit,
+     * or {@code null} if the system unit is a base unit (not a product of 
existing units).
+     *
+     * @return the base units and their exponent making up the system unit.
+     */
+    @Override
+    public Map<SystemUnit<?>, Integer> getBaseUnits() {
+        return target.getBaseUnits();
+    }
+
+    /**
+     * Casts this unit to a parameterized unit of specified nature or throw a 
{@code ClassCastException}
+     * if the dimension of the specified quantity and this unit's dimension do 
not match.
+     *
+     * @param  <T>   the type of the quantity measured by the unit.
+     * @param  type  the quantity class identifying the nature of the unit.
+     * @return this unit parameterized with the specified type.
+     * @throws ClassCastException if the dimension of this unit is different 
from the specified quantity dimension.
+     */
+    @Override
+    @SuppressWarnings("unchecked")
+    public <T extends Quantity<T>> Unit<T> asType(final Class<T> type) throws 
ClassCastException {
+        final Unit<T> alternate = target.asType(type);
+        if (target.equals(alternate)) {
+            return (Unit<T>) this;
+        }
+        return alternate.transform(toTarget);
+    }
+
+    /**
+     * Returns a converter of numeric values from this unit to another unit of 
same type.
+     *
+     * @param  that  the unit of same type to which to convert the numeric 
values.
+     * @return the converter from this unit to {@code that} unit.
+     * @throws UnconvertibleException if the converter can not be constructed.
+     */
+    @Override
+    public UnitConverter getConverterTo(final Unit<Q> that) throws 
UnconvertibleException {
+        if (that == this) {
+            return LinearConverter.IDENTITY;
+        }
+        ArgumentChecks.ensureNonNull("that", that);
+        UnitConverter c = toTarget;
+        if (target != that) {                           // Optimization for a 
common case.
+            final Unit<Q> step = that.getSystemUnit();
+            if (target != step && !target.equalsIgnoreMetadata(step)) {
+                // Should never occur unless parameterized type has been 
compromised.
+                throw new UnconvertibleException(incompatible(that));
+            }
+            c = step.getConverterTo(that).concatenate(c);
+        }
+        return c;
+    }
+
+    /**
+     * Returns a converter from this unit to the specified unit of unknown 
type.
+     * This method can be used when the quantity type of the specified unit is 
unknown at compile-time
+     * or when dimensional analysis allows for conversion between units of 
different type.
+     *
+     * @param  that  the unit to which to convert the numeric values.
+     * @return the converter from this unit to {@code that} unit.
+     * @throws IncommensurableException if this unit is not {@linkplain 
#isCompatible(Unit) compatible} with {@code that} unit.
+     *
+     * @see #isCompatible(Unit)
+     */
+    @Override
+    public UnitConverter getConverterToAny(final Unit<?> that) throws 
IncommensurableException {
+        if (that == this) {
+            return LinearConverter.IDENTITY;
+        }
+        ArgumentChecks.ensureNonNull("that", that);
+        UnitConverter c = toTarget;
+        if (target != that) {                           // Optimization for a 
common case.
+            final Unit<?> step = that.getSystemUnit();
+            if (target != step && !target.isCompatible(step)) {
+                throw new IncommensurableException(incompatible(that));
+            }
+            c = step.getConverterToAny(that).concatenate(c);
+        }
+        return c;
+    }
+
+    /**
+     * Unsupported operation for conventional units, as required by JSR-363 
specification.
+     *
+     * @param  symbol  the new symbol for the alternate unit.
+     * @return the alternate unit.
+     * @throws UnsupportedOperationException always thrown since this unit is 
not an unscaled standard unit.
+     *
+     * @see SystemUnit#alternate(String)
+     */
+    @Override
+    public Unit<Q> alternate(final String symbol) {
+        throw new 
UnsupportedOperationException(Errors.format(Errors.Keys.NonSystemUnit_1, this));
+    }
+
+    /**
+     * Ensures that the scale of measurement of this units is a ratio scale.
+     */
+    private void ensureRatioScale() {
+        if (!toTarget.isLinear()) {
+            throw new 
IllegalStateException(Errors.format(Errors.Keys.NonRatioUnit_1, this));
+        }
+    }
+
+    /**
+     * Returns the product of this unit with the one specified.
+     *
+     * @param  multiplier  the unit multiplier.
+     * @return {@code this} × {@code multiplier}
+     */
+    @Override
+    public Unit<?> multiply(final Unit<?> multiplier) {
+        ensureRatioScale();
+        return target.multiply(multiplier).transform(toTarget);
+    }
+
+    /**
+     * Returns the quotient of this unit with the one specified.
+     *
+     * @param  divisor  the unit divisor.
+     * @return {@code this} ÷ {@code divisor}
+     */
+    @Override
+    public Unit<?> divide(final Unit<?> divisor) {
+        ensureRatioScale();
+        return target.divide(divisor).transform(toTarget);
+    }
+
+    /**
+     * Returns a unit equals to this unit raised to an exponent.
+     *
+     * @param  n  the exponent.
+     * @return the result of raising this unit to the exponent.
+     */
+    @Override
+    public Unit<?> pow(final int n) {
+        ensureRatioScale();
+        final Unit<?> result = target.pow(n);
+        return (result == target) ? this : 
result.transform(LinearConverter.pow(toTarget, n, false));
+    }
+
+    /**
+     * Returns a unit equals to the given root of this unit.
+     *
+     * @param  n  the root's order.
+     * @return the result of taking the given root of this unit.
+     * @throws ArithmeticException if {@code n == 0}.
+     */
+    @Override
+    public Unit<?> root(final int n) {
+        ensureRatioScale();
+        final Unit<?> result = target.root(n);
+        return (result == target) ? this : 
result.transform(LinearConverter.pow(toTarget, n, true));
+    }
+
+    /**
+     * Returns the unit derived from this unit using the specified converter.
+     *
+     * @param  operation  the converter from the transformed unit to this unit.
+     * @return the unit after the specified transformation.
+     */
+    @Override
+    public Unit<Q> transform(final UnitConverter operation) {
+        ArgumentChecks.ensureNonNull("operation", operation);
+        return create(target, toTarget.concatenate(operation));
+    }
+}

Propchange: 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/ConventionalUnit.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/ConventionalUnit.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/LinearConverter.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/LinearConverter.java?rev=1765320&r1=1765319&r2=1765320&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/LinearConverter.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/LinearConverter.java
 [UTF-8] Mon Oct 17 15:57:29 2016
@@ -21,7 +21,10 @@ import java.util.Collections;
 import java.io.Serializable;
 import java.math.BigDecimal;
 import javax.measure.UnitConverter;
+import org.apache.sis.util.Debug;
 import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.math.DecimalFunctions;
+import org.apache.sis.math.MathFunctions;
 import org.apache.sis.internal.util.Numerics;
 
 
@@ -52,7 +55,7 @@ final class LinearConverter implements U
     /**
      * The identity linear converter.
      */
-    private static final LinearConverter IDENTITY = new LinearConverter(1, 0);
+    static final LinearConverter IDENTITY = new LinearConverter(1, 0);
 
     /**
      * The scale to apply for converting values.
@@ -89,6 +92,32 @@ final class LinearConverter implements U
     }
 
     /**
+     * Raises the given converter to the given power. This method assumes that 
the given converter
+     * {@linkplain #isLinear() is linear} (this is not verified) and take only 
the scale factor;
+     * the offset (if any) is ignored.
+     *
+     * @param  converter  the converter to raise to the given power.
+     * @param  n          the exponent.
+     * @param  root       {@code true} for raising to 1/n instead of n.
+     * @return the converter raised to the given power.
+     */
+    static LinearConverter pow(final UnitConverter converter, final int n, 
final boolean root) {
+        double scale = converter.convert(1.0) - converter.convert(0.0);
+        if (root) {
+            switch (n) {
+                case 2:  scale = Math.sqrt(scale); break;
+                case 3:  scale = Math.cbrt(scale); break;
+                default: scale = Math.pow(scale, 1.0 / n); break;
+            }
+        } else if (scale == 10) {
+            scale = MathFunctions.pow10(n);
+        } else {
+            scale = Math.pow(scale, n);
+        }
+        return create(scale, 0);
+    }
+
+    /**
      * Indicates if this converter is linear.
      * JSR-363 defines a converter as linear if:
      *
@@ -143,6 +172,7 @@ final class LinearConverter implements U
      */
     @Override
     public Number convert(Number value) {
+        ArgumentChecks.ensureNonNull("value", value);
         if (value instanceof BigDecimal) {
             if (scale != 1) {
                 value = ((BigDecimal) 
value).multiply(BigDecimal.valueOf(scale));
@@ -151,7 +181,14 @@ final class LinearConverter implements U
                 value = ((BigDecimal) value).add(BigDecimal.valueOf(offset));
             }
         } else if (!isIdentity()) {
-            value = convert(value.doubleValue());
+            final double x;
+            if (value instanceof Float) {
+                // Because unit conversion factors are usually defined in base 
10.
+                x = DecimalFunctions.floatToDouble((Float) value);
+            } else {
+                x = value.doubleValue();
+            }
+            value = convert(x);
         }
         return value;
     }
@@ -216,8 +253,11 @@ final class LinearConverter implements U
     }
 
     /**
-     * Returns a string representation of this converter.
+     * Returns a string representation of this converter for debugging purpose.
+     * This string representation may change in any future SIS release.
+     * Current format is of the form "y = scale⋅x + offset".
      */
+    @Debug
     @Override
     public String toString() {
         final StringBuilder buffer = new StringBuilder().append("\uD835\uDC66 
= ");

Modified: 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/SystemUnit.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/SystemUnit.java?rev=1765320&r1=1765319&r2=1765320&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/SystemUnit.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/SystemUnit.java
 [UTF-8] Mon Oct 17 15:57:29 2016
@@ -22,7 +22,12 @@ import java.io.ObjectStreamException;
 import javax.measure.Unit;
 import javax.measure.Quantity;
 import javax.measure.Dimension;
+import javax.measure.UnitConverter;
+import javax.measure.UnconvertibleException;
+import javax.measure.IncommensurableException;
+import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.ObjectConverters;
+import org.apache.sis.util.resources.Errors;
 import org.apache.sis.internal.converter.SurjectiveConverter;
 
 
@@ -39,9 +44,14 @@ import org.apache.sis.internal.converter
  * @version 0.8
  * @module
  */
-abstract class SystemUnit<Q extends Quantity<Q>> extends AbstractUnit<Q> {
+final class SystemUnit<Q extends Quantity<Q>> extends AbstractUnit<Q> {
     /**
-     * The type of quantity that uses this unit.
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 4097466138698631914L;
+
+    /**
+     * The type of quantity that uses this unit, or {@code null} if unknown.
      */
     final Class<Quantity<Q>> quantity;
 
@@ -53,6 +63,7 @@ abstract class SystemUnit<Q extends Quan
     /**
      * Creates a new unit having the given symbol and EPSG code.
      *
+     * @param  quantity   the type of quantity that uses this unit, or {@code 
null} if unknown.
      * @param  dimension  the unit dimension.
      * @param  name       the unit name,   or {@code null} if this unit has no 
specific name.
      * @param  symbol     the unit symbol, or {@code null} if this unit has no 
specific symbol.
@@ -67,6 +78,20 @@ abstract class SystemUnit<Q extends Quan
     }
 
     /**
+     * Returns a unit of the given dimension with default name and symbol.
+     */
+    private SystemUnit<?> create(final UnitDimension dim) {
+        if (dim == dimension) {
+            return this;
+        }
+        SystemUnit<?> result = Units.get(dim);
+        if (result == null) {
+            result = new SystemUnit<>(null, dim, null, null, (short) 0);
+        }
+        return result;
+    }
+
+    /**
      * Returns the dimension of this unit.
      * Two units {@code u1} and {@code u2} are {@linkplain #isCompatible(Unit) 
compatible}
      * if and only if {@code u1.getDimension().equals(u2.getDimension())}.
@@ -161,4 +186,212 @@ abstract class SystemUnit<Q extends Quan
             return INSTANCE;
         }
     }
+
+    /**
+     * Casts this unit to a parameterized unit of specified nature or throw a 
{@code ClassCastException}
+     * if the dimension of the specified quantity and this unit's dimension do 
not match.
+     *
+     * @param  <T>   the type of the quantity measured by the unit.
+     * @param  type  the quantity class identifying the nature of the unit.
+     * @return this unit parameterized with the specified type.
+     * @throws ClassCastException if the dimension of this unit is different 
from the specified quantity dimension.
+     */
+    @Override
+    @SuppressWarnings("unchecked")
+    public <T extends Quantity<T>> Unit<T> asType(final Class<T> type) throws 
ClassCastException {
+        ArgumentChecks.ensureNonNull("type", type);
+        if (type == quantity) {
+            return (Unit<T>) this;
+        }
+        if (dimension.isDimensionless()) {
+            final SystemUnit<T> target = Units.get(type);
+            if (target != null && target.dimension.isDimensionless()) {
+                return target;
+            }
+        }
+        throw new 
ClassCastException(Errors.format(Errors.Keys.CanNotConvertFromType_2,
+                "Unit<" + (quantity != null ? quantity.getSimpleName() : "?") 
+ '>',
+                "Unit<" + type.getSimpleName() + '>'));
+    }
+
+    /**
+     * Returns {@code true} if this unit is equals to the given unit ignoring 
name, symbol and EPSG code.
+     * This method should always returns {@code true} if parameterized type 
has not been compromised with
+     * raw types or unchecked casts.
+     *
+     * @param  other  the other unit, which must be a system unit.
+     */
+    final boolean equalsIgnoreMetadata(final Unit<Q> other) {
+        if (quantity != null && other instanceof SystemUnit<?>) {
+            /*
+             * For SIS implementation, we just need to compare the quantity 
class, if known.
+             * Two units for the same quantity implies that they are also for 
the same dimension.
+             */
+            final Class<?> c = ((SystemUnit<Q>) other).quantity;
+            if (c != null) {
+                final boolean status = (quantity == c);
+                assert status == dimension.equals(other.getDimension()) : this;
+                return status;
+            }
+        }
+        /*
+         * For foreigner implementations, comparing the units dimension is 
better than nothing.
+         * But this check is not as reliable as comparing the quantity classes.
+         */
+        assert other == other.getSystemUnit() : other;
+        return dimension.equals(other.getDimension());
+    }
+
+    /**
+     * Returns a converter of numeric values from this unit to another unit of 
same type.
+     *
+     * @param  that  the unit of same type to which to convert the numeric 
values.
+     * @return the converter from this unit to {@code that} unit.
+     * @throws UnconvertibleException if the converter can not be constructed.
+     */
+    @Override
+    public UnitConverter getConverterTo(final Unit<Q> that) throws 
UnconvertibleException {
+        ArgumentChecks.ensureNonNull("that", that);
+        final Unit<Q> step = that.getSystemUnit();
+        if (step != this && !equalsIgnoreMetadata(step)) {
+            // Should never occur unless parameterized type has been 
compromised.
+            throw new UnconvertibleException(incompatible(that));
+        }
+        if (step == that) {
+            return LinearConverter.IDENTITY;
+        }
+        /*
+         * At this point we know that the given units is not a system unit. 
Ask the conversion
+         * FROM the given units (before to inverse it) instead than TO the 
given units because
+         * in Apache SIS implementation, the former returns directly 
ConventionalUnit.toTarget
+         * while the later implies a recursive call to this method.
+         */
+        return that.getConverterTo(step).inverse();
+    }
+
+    /**
+     * Returns a converter from this unit to the specified unit of unknown 
type.
+     * This method can be used when the quantity type of the specified unit is 
unknown at compile-time
+     * or when dimensional analysis allows for conversion between units of 
different type.
+     *
+     * @param  that  the unit to which to convert the numeric values.
+     * @return the converter from this unit to {@code that} unit.
+     * @throws IncommensurableException if this unit is not {@linkplain 
#isCompatible(Unit) compatible} with {@code that} unit.
+     *
+     * @see #isCompatible(Unit)
+     */
+    @Override
+    public UnitConverter getConverterToAny(final Unit<?> that) throws 
IncommensurableException {
+        ArgumentChecks.ensureNonNull("that", that);
+        final Unit<?> step = that.getSystemUnit();
+        if (step != this && !isCompatible(step)) {
+            throw new IncommensurableException(incompatible(that));
+        }
+        if (step == that) {
+            return LinearConverter.IDENTITY;
+        }
+        // Same remark than in getConverterTo(Unit).
+        return that.getConverterToAny(step).inverse();
+    }
+
+    /**
+     * Returns a system unit equivalent to this unscaled standard unit but 
used in expressions
+     * to distinguish between quantities of a different nature but of the same 
dimensions.
+     *
+     * <p>The most important alternate unit in Apache SIS is {@link 
Units#RADIAN}, defined as below:</p>
+     *
+     * {@preformat java
+     *   Unit<Angle> RADIAN = ONE.alternate("rad").asType(Angle.class);
+     * }
+     *
+     * @param  symbol  the new symbol for the alternate unit.
+     * @return the alternate unit.
+     * @throws IllegalArgumentException if the specified symbol is already 
associated to a different unit.
+     */
+    @Override
+    public Unit<Q> alternate(final String symbol) {
+        ArgumentChecks.ensureNonNull("symbol", symbol);
+        if (symbol.equals(getSymbol())) {
+            return this;
+        }
+        // TODO: check for existing units.
+        return new SystemUnit<>(quantity, dimension, null, symbol, (short) 0);
+    }
+
+    /**
+     * Returns the product of this unit with the one specified.
+     *
+     * @param  multiplier  the unit multiplier.
+     * @return {@code this} × {@code multiplier}
+     */
+    @Override
+    public Unit<?> multiply(final Unit<?> multiplier) {
+        ArgumentChecks.ensureNonNull("multiplier", multiplier);
+        return combine(multiplier, false);
+    }
+
+    /**
+     * Returns the quotient of this unit with the one specified.
+     *
+     * @param  divisor  the unit divisor.
+     * @return {@code this} ÷ {@code divisor}
+     */
+    @Override
+    public Unit<?> divide(final Unit<?> divisor) {
+        ArgumentChecks.ensureNonNull("divisor", divisor);
+        return combine(divisor, true);
+    }
+
+    /**
+     * Implementation of {@link #multiply(Unit)} and {@link #divide(Unit)} 
methods.
+     */
+    private <T extends Quantity<T>> Unit<?> combine(final Unit<T> other, final 
boolean divide) {
+        final Unit<T> step = other.getSystemUnit();
+        final Dimension dim = step.getDimension();
+        Unit<?> result = create(divide ? dimension.divide(dim) : 
dimension.multiply(dim));
+        if (step != other) {
+            UnitConverter c = other.getConverterTo(step);
+            if (!c.isLinear()) {
+                throw new 
IllegalArgumentException(Errors.format(Errors.Keys.NonRatioUnit_1, other));
+            }
+            if (divide) c = c.inverse();
+            result = result.transform(c);
+        }
+        return result;
+    }
+
+    /**
+     * Returns a unit equals to this unit raised to an exponent.
+     *
+     * @param  n  the exponent.
+     * @return the result of raising this unit to the exponent.
+     */
+    @Override
+    public Unit<?> pow(final int n) {
+        return create(dimension.pow(n));
+    }
+
+    /**
+     * Returns a unit equals to the given root of this unit.
+     *
+     * @param  n  the root's order.
+     * @return the result of taking the given root of this unit.
+     * @throws ArithmeticException if {@code n == 0}.
+     */
+    @Override
+    public Unit<?> root(final int n) {
+        return create(dimension.root(n));
+    }
+
+    /**
+     * Returns the unit derived from this unit using the specified converter.
+     *
+     * @param  operation  the converter from the transformed unit to this unit.
+     * @return the unit after the specified transformation.
+     */
+    @Override
+    public Unit<Q> transform(final UnitConverter operation) {
+        ArgumentChecks.ensureNonNull("operation", operation);
+        return ConventionalUnit.create(this, operation);
+    }
 }

Modified: 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/UnitDimension.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/UnitDimension.java?rev=1765320&r1=1765319&r2=1765320&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/UnitDimension.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/UnitDimension.java
 [UTF-8] Mon Oct 17 15:57:29 2016
@@ -147,7 +147,7 @@ final class UnitDimension implements Dim
          */
         UnitDimension dim = POOL.get(components);
         if (dim == null) {
-            shareFractionInstances(components);
+            components.replaceAll((c, power) -> power.unique());
             components = CollectionsExt.unmodifiableOrCopy(components);
             dim = new UnitDimension(components);
             final UnitDimension c = POOL.putIfAbsent(components, dim);
@@ -159,27 +159,19 @@ final class UnitDimension implements Dim
     }
 
     /**
-     * Replaces the {@link Fraction} values in the given map by unique 
instances.
-     * This is a micro-optimisation saving a little bit of memory and 
performance
-     * in the common case where all dimensions share a small set of power 
values.
+     * Invoked on deserialization for returning a unique instance of {@code 
UnitDimension}.
      */
-    private static void shareFractionInstances(final 
Map<UnitDimension,Fraction> components) {
-        components.replaceAll((c, power) -> power.unique());
+    Object readResolve() throws ObjectStreamException {
+        final UnitDimension dim = POOL.putIfAbsent(components, this);
+        return (dim != null) ? dim : this;
     }
 
     /**
-     * Invoked on deserialization for returning a unique instance of {@code 
UnitDimension}.
+     * Returns {@code true} if this {@code UnitDimension} has no components.
+     * Many dimensionless units exist for different quantities as angles, 
parts per million, <i>etc.</i>
      */
-    Object readResolve() throws ObjectStreamException {
-        UnitDimension dim = POOL.get(components);
-        if (dim == null) {
-            shareFractionInstances(components);
-            dim = POOL.putIfAbsent(components, this);
-            if (dim == null) {
-                return this;
-            }
-        }
-        return dim;
+    final boolean isDimensionless() {
+        return components.isEmpty();
     }
 
     /**
@@ -223,7 +215,7 @@ final class UnitDimension implements Dim
      * @return {@code this} × {@code multiplicand}
      */
     @Override
-    public Dimension multiply(final Dimension multiplicand) {
+    public UnitDimension multiply(final Dimension multiplicand) {
         return combine(multiplicand, (sum, toAdd) -> {
             sum = sum.add(toAdd);
             return (sum.numerator != 0) ? sum : null;
@@ -237,7 +229,7 @@ final class UnitDimension implements Dim
      * @return {@code this} ∕ {@code divisor}
      */
     @Override
-    public Dimension divide(final Dimension divisor) {
+    public UnitDimension divide(final Dimension divisor) {
         return combine(divisor, (sum, toRemove) -> {
             sum = sum.subtract(toRemove);
             return (sum.numerator != 0) ? sum : null;
@@ -251,7 +243,7 @@ final class UnitDimension implements Dim
      * @param  mapping the operation to apply between the powers of {@code 
this} and {@code other} dimensions.
      * @return the product of this dimension by the given dimension raised to 
the given power.
      */
-    private Dimension combine(final Dimension other, final 
BiFunction<Fraction, Fraction, Fraction> mapping) {
+    private UnitDimension combine(final Dimension other, final 
BiFunction<Fraction, Fraction, Fraction> mapping) {
         final Map<UnitDimension,Fraction> product = new 
LinkedHashMap<>(components);
         for (final Map.Entry<? extends Dimension, Fraction> entry : 
getBaseDimensions(other).entrySet()) {
             final Dimension dim = entry.getKey();
@@ -271,7 +263,7 @@ final class UnitDimension implements Dim
      * @param  n  power to raise this dimension to (can be negative).
      * @return {@code this}ⁿ
      */
-    private Dimension pow(final Fraction n) {
+    private UnitDimension pow(final Fraction n) {
         final Map<UnitDimension,Fraction> product = new 
LinkedHashMap<>(components);
         product.replaceAll((dim, power) -> power.multiply(n));
         return create(product);
@@ -284,7 +276,7 @@ final class UnitDimension implements Dim
      * @return {@code this}ⁿ
      */
     @Override
-    public Dimension pow(final int n) {
+    public UnitDimension pow(final int n) {
         switch (n) {
             case 0:  return NONE;
             case 1:  return this;
@@ -299,7 +291,7 @@ final class UnitDimension implements Dim
      * @return {@code this} raised to power 1/n.
      */
     @Override
-    public Dimension root(final int n) {
+    public UnitDimension root(final int n) {
         switch (n) {
             case 0:  throw new 
ArithmeticException(Errors.format(Errors.Keys.IllegalArgumentValue_2, "n", 0));
             case 1:  return this;

Modified: 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java?rev=1765320&r1=1765319&r2=1765320&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java
 [UTF-8] Mon Oct 17 15:57:29 2016
@@ -58,10 +58,11 @@ import static org.apache.sis.measure.Sex
  */
 public final class Units extends Static {
     /**
-     * The units for given {@link UnitDimension} instances. This map contains 
mostly SI units (no imperial units)
-     * with the addition of some alternative units. This map must be 
unmodified after it has been populated.
+     * The units for given {@link UnitDimension} or {@code Class<Quantity>} 
instances.
+     * This map contains mostly SI units (no imperial units) with the addition 
of some alternative units.
+     * This map must be unmodified after it has been populated.
      */
-    private static final Map<UnitDimension, SystemUnit<?>> SYSTEM = new 
HashMap<>();
+    private static final Map<Object, SystemUnit<?>> SYSTEM = new HashMap<>();
 
     /**
      * Invoked by {@code Units} static class initializer for registering SI 
base and derived units.
@@ -69,12 +70,20 @@ public final class Units extends Static
      * populated in a single thread by the {@code Units} class initializer, 
then never modified.
      */
     private static void add(final SystemUnit<?> unit) {
-        if (SYSTEM.put(unit.dimension, unit) != null) {
+        if (SYSTEM.put(unit.quantity, unit) != null && 
SYSTEM.put(unit.dimension, unit) != null) {
             throw new AssertionError();                 // Shall not map the 
same dimension twice.
         }
     }
 
     /**
+     * Returns the unit for the given dimension, or {@code null} if none.
+     */
+    @SuppressWarnings("unchecked")
+    static <Q extends Quantity<Q>> SystemUnit<Q> get(final Class<Q> type) {
+        return (SystemUnit<Q>) SYSTEM.get(type);
+    }
+
+    /**
      * Returns the unit for the given dimension, or {@code null} if none.
      */
     static SystemUnit<?> get(final Dimension dim) {

Modified: 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java?rev=1765320&r1=1765319&r2=1765320&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
 [UTF-8] Mon Oct 17 15:57:29 2016
@@ -574,11 +574,21 @@ public final class Errors extends Indexe
         public static final short NonLinearUnit_1 = 100;
 
         /**
+         * The scale of measurement for “{0}” unit is not a ratio scale.
+         */
+        public static final short NonRatioUnit_1 = 162;
+
+        /**
          * “{0}” is not a scale unit.
          */
         public static final short NonScaleUnit_1 = 101;
 
         /**
+         * “{0}” is not a fundamental or derived unit.
+         */
+        public static final short NonSystemUnit_1 = 161;
+
+        /**
          * “{0}” is not a time unit.
          */
         public static final short NonTemporalUnit_1 = 102;

Modified: 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties?rev=1765320&r1=1765319&r2=1765320&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
 [ISO-8859-1] (original)
+++ 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
 [ISO-8859-1] Mon Oct 17 15:57:29 2016
@@ -126,6 +126,8 @@ NonAngularUnit_1                  = \u20
 NonLinearUnit_1                   = \u201c{0}\u201d is not a linear unit.
 NonScaleUnit_1                    = \u201c{0}\u201d is not a scale unit.
 NonTemporalUnit_1                 = \u201c{0}\u201d is not a time unit.
+NonSystemUnit_1                   = \u201c{0}\u201d is not a fundamental or 
derived unit.
+NonRatioUnit_1                    = The scale of measurement for 
\u201c{0}\u201d unit is not a ratio scale.
 NotABackwardReference_1           = No element for the \u201c{0}\u201d 
identifier, or the identifier is a forward reference.
 NotAKeyValuePair_1                = \u201c{0}\u201d is not a key-value pair.
 NotANumber_1                      = Argument \u2018{0}\u2019 shall not be NaN 
(Not-a-Number).

Modified: 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties?rev=1765320&r1=1765319&r2=1765320&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
 [ISO-8859-1] (original)
+++ 
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
 [ISO-8859-1] Mon Oct 17 15:57:29 2016
@@ -123,6 +123,8 @@ NonAngularUnit_1                  = \u00
 NonLinearUnit_1                   = \u00ab\u202f{0}\u202f\u00bb n\u2019est pas 
une unit\u00e9 de longueurs.
 NonScaleUnit_1                    = \u00ab\u202f{0}\u202f\u00bb n\u2019est pas 
une unit\u00e9 d\u2019\u00e9chelles.
 NonTemporalUnit_1                 = \u00ab\u202f{0}\u202f\u00bb n\u2019est pas 
une unit\u00e9 de temps.
+NonSystemUnit_1                   = \u00ab\u202f{0}\u202f\u00bb n\u2019est pas 
une unit\u00e9 fondamentale ou d\u00e9riv\u00e9e.
+NonRatioUnit_1                    = L\u2019\u00e9chelle de mesure de 
l\u2019unit\u00e9 \u00ab\u202f{0}\u202f\u00bb n\u2019est pas une \u00e9chelle 
de rapports.
 NotABackwardReference_1           = Il n\u2019y a pas d\u2019\u00e9l\u00e9ment 
pour l\u2019identifiant \u201c{0}\u201d, ou l\u2019identifiant est une 
r\u00e9f\u00e9rence vers l\u2019avant.
 NotAKeyValuePair_1                = \u00ab\u202f{0}\u202f\u00bb n\u2019est pas 
une paire cl\u00e9-valeur.
 NotANumber_1                      = L\u2019argument \u2018{0}\u2019 ne doit 
pas \u00eatre NaN (Not-a-Number).


Reply via email to