001/*
002 * International System of Units (SI)
003 * Copyright (c) 2005-2019, Jean-Marie Dautelle, Werner Keil and others.
004 *
005 * All rights reserved.
006 *
007 * Redistribution and use in source and binary forms, with or without modification,
008 * are permitted provided that the following conditions are met:
009 *
010 * 1. Redistributions of source code must retain the above copyright notice,
011 *    this list of conditions and the following disclaimer.
012 *
013 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
014 *    and the following disclaimer in the documentation and/or other materials provided with the distribution.
015 *
016 * 3. Neither the name of JSR-385, Units of Measurement nor the names of their contributors may be used to
017 *    endorse or promote products derived from this software without specific prior written permission.
018 *
019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
021 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
022 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
023 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
026 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029 */
030package si.uom;
031
032import static si.uom.SI.AVOGADRO_CONSTANT_VALUE;
033import static si.uom.SI.ELEMENTARY_CHARGE_VALUE;
034import static tech.units.indriya.AbstractUnit.ONE;
035import static javax.measure.MetricPrefix.CENTI;
036import static javax.measure.MetricPrefix.FEMTO;
037import static javax.measure.MetricPrefix.MEGA;
038import static tech.units.indriya.unit.Units.*;
039
040import javax.measure.Unit;
041import javax.measure.quantity.Acceleration;
042import javax.measure.quantity.AmountOfSubstance;
043import javax.measure.quantity.Angle;
044import javax.measure.quantity.Area;
045import javax.measure.quantity.Dimensionless;
046import javax.measure.quantity.ElectricCharge;
047import javax.measure.quantity.ElectricCurrent;
048import javax.measure.quantity.Energy;
049import javax.measure.quantity.Force;
050import javax.measure.quantity.Frequency;
051import javax.measure.quantity.Illuminance;
052import javax.measure.quantity.Length;
053import javax.measure.quantity.MagneticFlux;
054import javax.measure.quantity.MagneticFluxDensity;
055import javax.measure.quantity.Mass;
056import javax.measure.quantity.Power;
057import javax.measure.quantity.Pressure;
058import javax.measure.quantity.RadiationDoseAbsorbed;
059import javax.measure.quantity.RadiationDoseEffective;
060import javax.measure.quantity.Radioactivity;
061import javax.measure.quantity.SolidAngle;
062import javax.measure.quantity.Speed;
063import javax.measure.quantity.Temperature;
064import javax.measure.quantity.Time;
065
066import si.uom.quantity.DynamicViscosity;
067import si.uom.quantity.IonizingRadiation;
068import si.uom.quantity.KinematicViscosity;
069import si.uom.quantity.Level;
070import si.uom.quantity.Luminance;
071import si.uom.quantity.MagneticFieldStrength;
072import tech.units.indriya.AbstractSystemOfUnits;
073import tech.units.indriya.AbstractUnit;
074import tech.units.indriya.format.SimpleUnitFormat;
075import tech.units.indriya.function.AbstractConverter;
076import tech.units.indriya.function.LogConverter;
077import tech.units.indriya.function.MultiplyConverter;
078import tech.units.indriya.unit.ProductUnit;
079import tech.units.indriya.unit.TransformedUnit;
080
081/**
082 * <p>
083 * This class contains units that are not part of the International System of
084 * Units, that is, they are outside the SI, but some are still widely used.
085 * </p>
086 * 
087 * <p>
088 * This class is not intended to be implemented by clients.
089 * </p>
090 * 
091 * @noimplement This class is not intended to be implemented by clients.
092 * @noextend This class is not intended to be extended by clients.
093 * 
094 * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
095 * @author <a href="mailto:werner@uom.si">Werner Keil</a>
096 * @version 1.4, June 21, 2019
097 * @see <a href=
098 *      "https://en.wikipedia.org/wiki/Non-SI_units_mentioned_in_the_SI#Common_units_not_officially_sanctioned">Wikipedia:
099 *      Common Units not officially sanctioned</a>
100 */
101public class NonSI extends AbstractSystemOfUnits {
102    private static final String SYSTEM_NAME = "Non-SI Units";
103
104    /**
105     * Holds the standard gravity constant: 9.80665 m/s² exact.
106     */
107    private static final int STANDARD_GRAVITY_DIVIDEND = 980665;
108
109    private static final int STANDARD_GRAVITY_DIVISOR = 100000;
110
111    /**
112     * Holds the avoirdupois pound: 0.45359237 kg exact
113     */
114    private static final int AVOIRDUPOIS_POUND_DIVIDEND = 45359237;
115
116    private static final int AVOIRDUPOIS_POUND_DIVISOR = 100000000;
117
118    private static final NonSI INSTANCE = new NonSI();
119    
120    /////////////////////////////////////////////////////////////////
121    // Units outside the SI that are accepted for use with the SI. //
122    /////////////////////////////////////////////////////////////////
123
124    /**
125     * An angle unit accepted for use with SI units (standard name
126     * <code>deg</code>).
127     */
128    public static final Unit<Angle> DEGREE_ANGLE = addUnit(
129            new TransformedUnit<Angle>(RADIAN, MultiplyConverter.ofPiExponent(1).concatenate(MultiplyConverter.ofRational(1, 180))),
130            "Degree Angle", "deg");
131
132    /**
133     * An angle unit accepted for use with SI units (standard name <code>'</code>).
134     */
135    public static final Unit<Angle> MINUTE_ANGLE = addUnit(new TransformedUnit<Angle>(RADIAN,
136            MultiplyConverter.ofPiExponent(1).concatenate(MultiplyConverter.ofRational(1, 180 * 60))), "Minute Angle", "'");
137
138    /**
139     * An angle unit accepted for use with SI units (standard name <code>''</code>).
140     */
141    public static final Unit<Angle> SECOND_ANGLE = addUnit(
142            new TransformedUnit<Angle>(RADIAN,
143                    MultiplyConverter.ofPiExponent(1).concatenate(MultiplyConverter.ofRational(1, 180 * 60 * 60))),
144            "Second Angle", "''");
145
146    /**
147     * An energy unit accepted for use with SI units (standard name
148     * <code>eV</code>). The electronvolt is the kinetic energy acquired by an
149     * electron passing through a potential difference of 1 V in vacuum. The value
150     * must be obtained by experiment, and is therefore not known exactly.
151     */
152    public static final Unit<Energy> ELECTRON_VOLT = addUnit(
153            new TransformedUnit<Energy>(JOULE, MultiplyConverter.of(1.602176487E-19)), "Electron Volt", "eV");
154    // CODATA 2006 - http://physics.nist.gov/cuu/Constants/codata.pdf
155
156    /**
157     * A mass unit accepted for use with SI units (standard name <code>u</code>).
158     * The unified atomic mass unit is equal to 1/12 of the mass of an unbound atom
159     * of the nuclide 12C, at rest and in its ground state. The value must be
160     * obtained by experiment, and is therefore not known exactly.
161     */
162    public static final Unit<Mass> UNIFIED_ATOMIC_MASS = addUnit(
163            new TransformedUnit<Mass>(KILOGRAM, MultiplyConverter.of(1.660538782E-27)), "Unified atomic mass", "u",
164            true);
165    // CODATA 2006 - http://physics.nist.gov/cuu/Constants/codata.pdf
166
167    /**
168     * The dalton (Da) and the unified atomic mass unit (u) are alternative names (and symbols) for the same unit, 
169     * equal to 1/12 times the mass of a free carbon 12 atom, at rest and in its ground state. 
170     * The dalton is often combined with SI prefixes, for example to express the masses of large molecules in kilodaltons, kDa, or megadaltons, MDa, 
171     * or to express the values of small mass differences of atoms or molecules in nanodaltons, nDa, or even picodaltons, pDa.
172     */
173    public static final Unit<Mass> DALTON = addUnit(
174            new TransformedUnit<Mass>(UNIFIED_ATOMIC_MASS, AbstractConverter.IDENTITY), "Dalton", "Da");
175    
176    /**
177     * A length unit accepted for use with SI units (standard name <code>UA</code>).
178     * The astronomical unit is a unit of length. Its value is such that, when used
179     * to describe the motion of bodies in the solar system, the heliocentric
180     * gravitation constant is (0.017 202 098 95)2 ua3·d-2. The value must be
181     * obtained by experiment, and is therefore not known exactly.
182     */
183    public static final Unit<Length> ASTRONOMICAL_UNIT = addUnit(
184            new TransformedUnit<Length>(METRE, MultiplyConverter.of(149597871000.0)), "Astronomical Unit", "UA");
185    // Best estimate source: http://maia.usno.navy.mil/NSFA/CBE.html
186
187    /**
188     * An angle unit accepted for use with SI units (standard name <code>ha</code>).
189     */
190    public static final Unit<Area> HECTARE = addUnit(
191            new TransformedUnit<Area>(SQUARE_METRE, MultiplyConverter.ofRational(10000, 1)), "Hectare", "ha");
192
193    ///////////////////
194    // Dimensionless //
195    ///////////////////
196    /**
197     * A dimensionless unit equals to <code>pi</code> (standard name
198     * <code>Ï€</code>).
199     */
200    public static final Unit<Dimensionless> PI = addUnit(ONE.multiply(StrictMath.PI));
201
202    /////////////////////////
203    // Amount of substance //
204    /////////////////////////
205    /**
206     * A unit of amount of substance equals to one atom (standard name
207     * <code>atom</code>).
208     */
209    public static final Unit<AmountOfSubstance> ATOM = addUnit(MOLE.divide(AVOGADRO_CONSTANT_VALUE));
210
211    ////////////
212    // Length //
213    ////////////
214
215    /**
216     * A unit of length equal to <code>1E-10 m</code> (standard name
217     * <code>Å</code>).
218     * 
219     * @see <a href="https://en.wikipedia.org/wiki/%C3%85ngstr%C3%B6m"> Wikipedia:
220     *      Ångström</a>
221     */
222    public static final Unit<Length> ANGSTROM = addUnit(METRE.divide(10000000000L), "\u00C5ngstr\u00F6m", "\u00C5");
223
224    /**
225     * A unit of length equal to the distance that light travels in one year through
226     * a vacuum (standard name <code>ly</code>).
227     */
228    public static final Unit<Length> LIGHT_YEAR = addUnit(METRE.multiply(9.460528405e15), "Light year", "ly");
229
230    /**
231     * A unit of length equal to the distance at which a star would appear to shift
232     * its position by one arcsecond over the course the time (about 3 months) in
233     * which the Earth moves a distance of {@link #ASTRONOMICAL_UNIT} in the
234     * direction perpendicular to the direction to the star (standard name
235     * <code>pc</code>).
236     */
237    public static final Unit<Length> PARSEC = addUnit(METRE.multiply(30856770e9));
238
239    /**
240     * A unit of length equal to <code>1852.0 m</code> (standard name
241     * <code>nmi</code>).
242     */
243    public static final Unit<Length> NAUTICAL_MILE = addUnit(METRE.multiply(1852), "Nautical mile", "nmi");
244
245        /**
246         * The Bohr radius (a0 or rBohr) is a physical constant, approximately equal to the most probable distance between the nucleus and the electron in a hydrogen atom in its ground state.
247         * It is named after Niels Bohr, due to its role in the Bohr model of an atom. Its value is 5.2917721067(12)×10−11 m.
248         */
249        public static final Unit<Length> BOHR_RADIUS = addUnit(METRE.multiply(5.291772106712E-11), "Bohr Radius", "a0");
250
251    ////////////
252    // Area   //
253    ////////////
254
255    /**
256     * A barn (symbol: <code>b</code>) is a unit of area equal to 10<sup>−28</sup>
257     * <code>m2</code> (100 <code>fm2</code>)
258     */
259    public static final Unit<Area> BARN = addUnit(new ProductUnit<Area>(FEMTO(METRE).pow(2)).multiply(100));
260
261    ////////////
262    // Time   //
263    ////////////
264
265    /**
266     * A unit of duration equal to the time required for a complete rotation of the
267     * earth in reference to any star or to the vernal equinox at the meridian,
268     * equal to 23 hours, 56 minutes, 4.09 seconds (standard name
269     * <code>day_sidereal</code>).
270     */
271    public static final Unit<Time> DAY_SIDEREAL = addUnit(SECOND.multiply(86164.09));
272        
273    /**
274         * A unit of duration equal to 365 {@link #DAY} (standard name
275         * <code>year</code>).
276         */
277        public static final Unit<Time> YEAR_CALENDAR = addUnit(DAY.multiply(365));
278
279    /**
280     * A unit of duration equal to one complete revolution of the earth about the
281     * sun, relative to the fixed stars, or 365 days, 6 hours, 9 minutes, 9.54
282     * seconds (standard name <code>year_sidereal</code>).
283     */
284    public static final Unit<Time> YEAR_SIDEREAL = addUnit(SECOND.multiply(31558149.54));
285
286    /**
287     * The Julian year, as used in astronomy and other sciences, is a time unit
288     * defined as exactly 365.25 days. This is the normal meaning of the unit "year"
289     * (symbol "a" from the Latin annus, annata) used in various scientific
290     * contexts.
291     */
292    public static final Unit<Time> YEAR_JULIEN = addUnit(SECOND.multiply(31557600));
293
294    //////////
295    // Mass //
296    //////////
297    /**
298     * A unit of mass equal to 1/12 the mass of the carbon-12 atom (standard name
299     * <code>u</code>).
300     */
301    public static final Unit<Mass> ATOMIC_MASS = addUnit(KILOGRAM.multiply(1e-3 / AVOGADRO_CONSTANT_VALUE));
302
303    /**
304     * A unit of mass equal to the mass of the electron (standard name
305     * <code>me</code>).
306     */
307    public static final Unit<Mass> ELECTRON_MASS = addUnit(KILOGRAM.multiply(9.10938188E-31));
308    
309    /**
310     * A mass unit accepted for use with SI units (standard name <code>t</code>).
311     */
312    public static final Unit<Mass> TONNE = addUnit(new TransformedUnit<Mass>(KILOGRAM, MultiplyConverter.ofRational(1000, 1)),
313            "Tonne", "t");
314
315    /////////////////////
316    // Electric charge //
317    /////////////////////
318    /**
319     * A unit of electric charge equal to the charge on one electron (standard name
320     * <code>e</code>).
321     */
322    @SuppressWarnings("unused")
323        private static final Unit<ElectricCharge> E = COULOMB.multiply(ELEMENTARY_CHARGE_VALUE);
324
325    /**
326     * A unit of electric charge equal to equal to the product of Avogadro's number
327     * (see {@link SI#MOLE}) and the charge (1 e) on a single electron (standard
328     * name <code>Fd</code>).
329     */
330    public static final Unit<ElectricCharge> FARADAY = addUnit(
331            COULOMB.multiply(ELEMENTARY_CHARGE_VALUE * AVOGADRO_CONSTANT_VALUE)); // e/mol
332
333    /**
334     * A unit of electric charge which exerts a force of one dyne on an equal charge
335     * at a distance of one centimeter (standard name <code>Fr</code>).
336     */
337    public static final Unit<ElectricCharge> FRANKLIN = addUnit(COULOMB.multiply(3.3356e-10));
338
339    /////////////////
340    // Temperature //
341    /////////////////
342    /**
343     * A unit of temperature equal to <code>5/9 °K</code> (standard name
344     * <code>°R</code>).
345     */
346    public static final Unit<Temperature> RANKINE = addUnit(KELVIN.multiply(5).divide(9));
347
348    ///////////
349    // Angle //
350    ///////////
351
352    /**
353     * A unit of angle equal to a full circle or <code>2<i>&pi;</i>
354     * {@link SI#RADIAN}</code> (standard name <code>rev</code>).
355     */
356    public static final Unit<Angle> REVOLUTION = addUnit(RADIAN.multiply(2).multiply(Math.PI).asType(Angle.class));
357
358    //////////////
359    // Speed    //
360    //////////////
361    /**
362     * The Natural Unit of {@link Speed}, a unit of velocity relative to the speed of light (standard name
363     * <code>c</code>).
364     */
365    public static final Unit<Speed> C = addUnit(METRE_PER_SECOND.multiply(299792458));
366
367    /**
368     * A unit of velocity expressing the number of {@link #NAUTICAL_MILE nautical
369     * miles} per {@link #HOUR hour} (abbreviation <code>kn</code>).
370     */
371    public static final Unit<Speed> KNOT = addUnit(NAUTICAL_MILE.divide(HOUR).asType(Speed.class), "Knot", "kn");
372
373    //////////////////
374    // Acceleration //
375    //////////////////
376    
377    /**
378     * Standard acceleration of free fall, sometimes abbreviated as standard gravity. A unit of acceleration equal to the gravity at the earth's surface (standard
379     * name <code>g<sub>n</sub></code>).
380     */
381    public static final Unit<Acceleration> STANDARD_GRAVITY = addUnit(METRE_PER_SQUARE_SECOND.multiply(STANDARD_GRAVITY_DIVIDEND)
382            .divide(STANDARD_GRAVITY_DIVISOR), "g\\u2099");
383    
384    /**
385     * A unit of acceleration equal to <code>1 cm s<sup>2</sup></code>  (standard
386     * name <code>Gal</code>).
387     */
388    public static final Unit<Acceleration> GAL = addUnit(
389            new ProductUnit<Acceleration>(CENTI(METRE).divide(SECOND.pow(2))));
390
391    //////////////////////
392    // Electric current //
393    //////////////////////
394    /**
395     * A unit of electric charge equal to the centimeter-gram-second electromagnetic
396     * unit of magnetomotive force, equal to <code>10/4
397     * &pi;ampere-turn</code> (standard name <code>Gi</code>).
398     */
399    public static final Unit<ElectricCurrent> GILBERT = addUnit(AMPERE.multiply(10).divide(4).multiply(PI)
400            .asType(ElectricCurrent.class));
401
402    ////////////
403    // Energy //
404    ////////////
405    /**
406     * A unit of energy equal to <code>1E-7 J</code> (standard name
407     * <code>erg</code>).
408     */
409    public static final Unit<Energy> ERG = addUnit(JOULE.divide(10000000));
410
411    /////////////////
412    // Luminance //
413    /////////////////
414    public static final Unit<Luminance> STILB = addUnit(
415            new ProductUnit<Luminance>(CANDELA.divide(CENTI(METRE).pow(2))));
416
417    /**
418     * A unit of luminance equal to <code>1E4 Lx</code> (standard name
419     * <code>La</code>).
420     */
421    public static final Unit<Luminance> LAMBERT = addUnit(new ProductUnit<Luminance>(STILB.divide(PI)));
422
423    /**
424     * A unit of illuminance equal to <code>1E4 Lx</code> (standard name
425     * <code>ph</code>).
426     */
427    public static final Unit<Illuminance> PHOT = addUnit(LUX.divide(1E4), "Phot", "ph");
428
429    ///////////////////
430    // Magnetic Flux //
431    ///////////////////
432    /**
433     * A unit of magnetic flux equal <code>1E-8 Wb</code> (standard name
434     * <code>Mx</code>).
435     */
436    public static final Unit<MagneticFlux> MAXWELL = addUnit(WEBER.divide(100000000));
437
438    ///////////////////////////
439    // Magnetic Flux Density //
440    ///////////////////////////
441    /**
442     * A unit of magnetic flux density equal <code>1000 A/m</code> (standard name
443     * <code>G</code>).
444     */
445    public static final Unit<MagneticFluxDensity> GAUSS = addUnit(TESLA.divide(10000));
446
447    /**
448     * A unit of magnetic field strength equal <code>(10<sup>3</sup>/4pi) A m–1</code> (standard name
449     * <code>Oe</code>).
450     */
451    public static final Unit<MagneticFieldStrength> OERSTED = addUnit(
452            new ProductUnit<>(SI.AMPERE_PER_METRE.multiply(250).divide(PI)), "Oersted", "Oe", true);
453    
454    ///////////
455    // Force //
456    ///////////
457    /**
458     * A unit of force equal to <code>1E-5 N</code> (standard name
459     * <code>dyn</code>).
460     */
461    public static final Unit<Force> DYNE = addUnit(NEWTON.divide(100000), "Dyne", "dyn", true);
462
463        /**
464         * A unit of force equal to <code>9.80665 N</code> (standard name
465         * <code>kgf</code>).
466         */
467        public static final Unit<Force> KILOGRAM_FORCE = addUnit(
468                        NEWTON.multiply(STANDARD_GRAVITY_DIVIDEND).divide(STANDARD_GRAVITY_DIVISOR), "kgf");
469
470    /**
471     * A unit of force equal to <code>{@link #POUND}·{@link #STANDARD_GRAVITY}</code> (standard
472     * name <code>lbf</code>).
473     */
474    @SuppressWarnings("unused")
475    private static final Unit<Force> POUND_FORCE = NEWTON.multiply(1L * AVOIRDUPOIS_POUND_DIVIDEND * STANDARD_GRAVITY_DIVIDEND)
476            .divide(1L * AVOIRDUPOIS_POUND_DIVISOR * STANDARD_GRAVITY_DIVISOR);
477
478        ///////////
479        // Power //
480        ///////////
481        /**
482         * A unit of power equal to the power required to raise a mass of 75 kilograms
483         * at a velocity of 1 meter per second (metric, standard name <code>hp</code>).
484         */
485        public static final Unit<Power> HORSEPOWER = addUnit(WATT.multiply(735.499));
486
487    //////////////
488    // Pressure //
489    //////////////
490
491    /**
492     * A unit of pressure equal to <code>100 kPa</code> (standard name
493     * <code>bar</code>).
494     */
495    public static final Unit<Pressure> BAR = addUnit(PASCAL.multiply(100000), "Bar", "b");
496
497    /**
498     * A unit of pressure equal to the pressure exerted at the Earth's surface by a
499     * column of mercury 1 millimeter high (standard name <code>mmHg</code> ).
500     */
501    public static final Unit<Pressure> MILLIMETRE_OF_MERCURY = addUnit(PASCAL.multiply(133.322));
502
503        /**
504         * A unit of pressure equal to the pressure exerted at the Earth's surface by a
505         * column of mercury 1 inch high (standard name <code>inHg</code>).
506         */
507        public static final Unit<Pressure> INCH_OF_MERCURY = addUnit(PASCAL.multiply(3386.388));
508
509    /////////////////////////////
510    // Radiation dose absorbed //
511    /////////////////////////////
512    /**
513     * A unit of radiation dose absorbed equal to a dose of 0.01 joule of energy per
514     * kilogram of mass (J/kg) (standard name <code>rd</code>).
515     */
516    public static final Unit<RadiationDoseAbsorbed> RAD = addUnit(GRAY.divide(100), "Rad", "rd");
517
518    /**
519     * A unit of radiation dose effective equal to <code>0.01 Sv</code> (standard
520     * name <code>rem</code>).
521     */
522    public static final Unit<RadiationDoseEffective> REM = addUnit(SIEVERT.divide(100));
523
524    //////////////////////////
525    // Radioactivity        //
526    //////////////////////////
527    /**
528     * A unit of radioctive activity equal to the activity of a gram of radium
529     * (standard name <code>Ci</code>).
530     */
531    public static final Unit<Radioactivity> CURIE = addUnit(BECQUEREL.multiply(37000000000L));
532
533    /**
534     * A unit of radioctive activity equal to 1 million radioactive disintegrations
535     * per second (standard name <code>Rd</code>).
536     */
537    protected static final Unit<Radioactivity> RUTHERFORD = addUnit(BECQUEREL.multiply(1000000));
538
539    /////////////////
540    // Solid angle //
541    /////////////////
542    /**
543     * A unit of solid angle equal to <code>4 <i>&pi;</i> steradians</code>
544     * (standard name <code>sphere</code>).
545     */
546    protected static final Unit<SolidAngle> SPHERE = addUnit(
547            STERADIAN.multiply(4).multiply(PI).asType(SolidAngle.class));
548
549    ///////////////
550    // Viscosity //
551    ///////////////
552    /**
553     * A unit of dynamic viscosity equal to <code>1 g/(cm·s)</code> (cgs unit).
554     */
555    public static final Unit<DynamicViscosity> POISE = addUnit(GRAM.divide(CENTI(METRE).multiply(SECOND)))
556            .asType(DynamicViscosity.class);
557
558    /**
559     * A unit of kinematic viscosity equal to <code>1 cm²/s</code> (cgs unit).
560     */
561    public static final Unit<KinematicViscosity> STOKES = addUnit(CENTI(METRE).pow(2).divide(SECOND))
562            .asType(KinematicViscosity.class);
563    
564    ///////////////
565    // Frequency //
566    ///////////////
567    /**
568     * A unit used to measure the frequency (rate) at which an imaging device
569     * produces unique consecutive images (standard name <code>fps</code>).
570     */
571    protected static final Unit<Frequency> FRAMES_PER_SECOND = addUnit(ONE.divide(SECOND)).asType(Frequency.class);
572
573    /**
574     * A unit used to measure the ionizing ability of radiation (standard name
575     * <code>R</code>).
576     * 
577     * @see <a href="https://en.wikipedia.org/wiki/Roentgen_(unit)"> Wikipedia:
578     *      Roentgen</a>
579     */
580    public static final Unit<IonizingRadiation> ROENTGEN = addUnit(
581            COULOMB.divide(KILOGRAM).multiply(2.58e-4).asType(IonizingRadiation.class), "Roentgen", "R", true);
582
583    ///////////////////////
584    // Logarithmic Units //
585    ///////////////////////
586
587    @SuppressWarnings({ "unchecked", "rawtypes" })
588    public static final Unit<Level<Dimensionless>> BEL = (Unit) addUnit(ONE.transform(new LogConverter(10)), "Bel", "B",
589            true);
590
591    @SuppressWarnings({ "unchecked", "rawtypes" })
592    public static final Unit<Level<Dimensionless>> NEPER = (Unit) addUnit(ONE.transform(new LogConverter(Math.E)),
593            "Neper", "Np", true);
594
595    /////////////////////
596    // Collection View //
597    /////////////////////
598
599    /**
600     * Default constructor (prevents this class from being instantiated).
601     */
602    private NonSI() {
603    }
604
605    /**
606     * Returns the unique instance of this class.
607     * 
608     * @return the NonSI instance.
609     */
610    public static NonSI getInstance() {
611        return INSTANCE;
612    }
613
614    public String getName() {
615        return SYSTEM_NAME;
616    }
617
618    /**
619     * Adds a new unit not mapped to any specified quantity type.
620     *
621     * @param unit
622     *            the unit being added.
623     * @return <code>unit</code>.
624     */
625    private static <U extends Unit<?>> U addUnit(U unit) {
626        INSTANCE.units.add(unit);
627        return unit;
628    }
629
630    /**
631     * Adds a new unit not mapped to any specified quantity type and puts a text as
632     * symbol or label.
633     *
634     * @param unit
635     *            the unit being added.
636     * @param name
637     *            the string to use as name
638     * @param text
639     *            the string to use as label or symbol
640     * @param isLabel
641     *            if the string should be used as a label or not
642     * @return <code>unit</code>.
643     */
644    private static <U extends Unit<?>> U addUnit(U unit, String name, String text, boolean isLabel) {
645        if (isLabel && text != null) {
646            SimpleUnitFormat.getInstance().label(unit, text);
647        }
648        if (name != null && unit instanceof AbstractUnit) {
649            return Helper.addUnit(INSTANCE.units, unit, name);
650        } else {
651            INSTANCE.units.add(unit);
652        }
653        return unit;
654    }
655
656    /**
657     * Adds a new unit not mapped to any specified quantity type and puts a text as
658     * symbol or label.
659     *
660     * @param unit
661     *            the unit being added.
662     * @param name
663     *            the string to use as name
664     * @param text
665     *            the string to use as label
666     * @return <code>unit</code>.
667     */
668    private static <U extends Unit<?>> U addUnit(U unit, String name, String text) {
669        return addUnit(unit, name, text, true);
670    }
671    /**
672     * Adds a new unit not mapped to any specified quantity type and puts a text
673     * as symbol or label.
674     *
675     * @param unit
676     *            the unit being added.
677     * @param text
678     *            the string to use as label or symbol
679     * @param isLabel
680     *            if the string should be used as a label or not
681     * @return <code>unit</code>.
682     */
683    private static <U extends Unit<?>> U addUnit(U unit, String text, boolean isLabel) {
684        return addUnit(unit, null, text, isLabel);
685    }
686    
687    /**
688     * Adds a new unit not mapped to any specified quantity type and puts a text
689     * as symbol or label.
690     *
691     * @param unit
692     *            the unit being added.
693     * @param text
694     *            the string to use as label or symbol
695     * @return <code>unit</code>.
696     */
697    private static <U extends Unit<?>> U addUnit(U unit, String text) {
698        return addUnit(unit, text, true);
699    }
700    
701    // //////////////////////////////////////////////////////////////////////////
702    // Label adjustments for Non-SI
703    static {
704        SimpleUnitFormat.getInstance().label(TONNE, "t");
705        SimpleUnitFormat.getInstance().label(MEGA(TONNE), "Mt");
706        SimpleUnitFormat.getInstance().alias(STANDARD_GRAVITY, "gn");
707    }
708}