Provides support for physical quantities, automatic error calculation (including numeric errors), and dimension-checking done in the form of class-type checking.

  1. Physical quantities:

    This package contains more than 40 predefined quantities with specific methods (e.g. Angle.sin(), Scalar.log()) and constants (e.g. Velocity.SPEED_OF_LIGHT, Mass.PROTON, Constant.µ0). The appropriate quantity sub-class is automatically instantiated when needed.

    Quantity classes support derivation, making the framework easily extendable. For example:

    
            // Derives from top Quantity class.
            public class MagneticDipoleMoment extends Quantity {
                private final static Factory FACTORY = new Factory(SI.AMPERE.multiply(SI.METER.pow(2))) {
                    protected Quantity create() {
                       return new MagneticDipoleMoment();
                    }
                };
            }
    
            // Derives from quantities other than the Quantity class.
            public class Altitude extends Length {
                private final static Factory FACTORY = new Factory(SI.METER.alternate("meter_height")) {
                    protected Quantity create() {
                       return new Altitude();
                    }
                };
            };
    Note: Mapping of the predefined quantities occurs when the library is initialized (Ref. {@link com.dautelle.JADE#initialize}). If the framework is extended (e.g. new quantity sub-classes) the application has to make sure that the new classes are initialized to ensure proper unit registration.
  2. Error calculations:

    Quantities take into account measurement errors as well as numeric errors! This can be illustrated with the following example:

              double x = 10864;
              double y = 18817;
              double z = 9 * Math.pow(x, 4)- Math.pow(y, 4) + 2 * Math.pow(y, 2);
              System.out.println("Result using double : " + z);
    
              > Result using double : 2.0
    The mathematically correct value is z=1. However, Java compilers using ANSI/IEEE double precision numbers evaluate z=2. Not even the first digit is correct! This is due to a rounding error occurring when subtracting two nearly equal floating point numbers. Now, lets write the same formula using our physical quantities:
              Scalar x = Scalar.valueOf(10864);
              Scalar y = Scalar.valueOf(18817);
              Scalar z = (Scalar) x.pow(4).multiply(9).subtract(y.pow(4)).add(y.pow(2).multiply(2));
              System.out.println("Result using physical quantities : " + z.doubleValue());
              System.out.println("Absolute error : " + z.getAbsoluteError());
    
              > Result using physical quantities : 2.0
              > Absolute error : 48.000000357627876
    The same result is returned, but now you know you cannot trust it!

    Quantities are displayed with the error on the last digit. This point can be illustrated with the following code:

              Length   x = (Length)   Quantity.valueOf(1, SI.METER);
              Velocity v = (Velocity) Quantity.valueOf(0.01, SI.METER.divide(SI.SECOND));
              Duration t = (Duration) Quantity.valueOf(1, SI.MICRO(SI.SECOND));
              for (int i=0; i < 10000000; i++) {
                  x = (Length) x.add(v.multiply(t));
              }
              System.out.println(x);
    
              > 1.10000000 m
    The exact value is guaranteed to be in the range: [1.09999999 m, 1.10000001 m] . The same calculation using double would have printed
              > 1.099999999392253
    with no idea on the accuracy of this result.

  3. Dimension checking:

    The system unit of a quantity determinates its class. For example, Quantity.valueOf("1 µm") and Quantity.valueOf("1.2 ft") return a Length instance (both "µm" and "ft" units are derived from SI.METER).

    Multiple physical models are supported (e.g. Standard, Relativistic, High-Energy, Quantum and Natural). The current model defines the conversions being allowed as well as the default units to output quantities. For example:

            final Quantity x = Length.valueOf(1, NonSI.INCH);
            System.out.println(x); // Default standard model, length are stated in meters.
            LocalContext.execute(new Runnable() {
                public void run() {
                    RelativisticModel.select(); // Selects the relativistic model.
                    System.out.println(x); // Lengths are stated in second.
                    Quantity y = x.add(Duration.valueOf("2.3 µs")); // Length and Duration can be added.
                    Mass m = Mass.massOf(Quantity.valueOf("12 GeV")); // Energy is compatible with mass (E=mc2)
                }
            });
            > 2.540000000000000E-2 m
            > 8.472528018033062E-11 s

    Custom units for quantity output is allowed. For example:

            Length x = (Length) Quantity.valueOf(123, SI.CENTI(SI.METER));
            Length.showAs(NonSI.INCH); // Context-local.
            System.out.println(x);
    
            > 48.42519685039370 in