001/*
002 *  Unit-API - Units of Measurement API for Java
003 *  Copyright (c) 2005-2016, Jean-Marie Dautelle, Werner Keil, V2COM.
004 *
005 * All rights reserved.
006 *
007 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
008 *
009 * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
010 *
011 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
012 *
013 * 3. Neither the name of JSR-363 nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
014 *
015 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
016 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
017 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
018 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
019 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
020 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
021 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
022 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
023 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
024 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
025 */
026package systems.uom.common;
027
028import static tec.units.ri.AbstractUnit.ONE;
029import static tec.units.ri.unit.Units.AMPERE;
030import static tec.units.ri.unit.Units.BECQUEREL;
031import static tec.units.ri.unit.Units.COULOMB;
032import static tec.units.ri.unit.Units.GRAY;
033import static tec.units.ri.unit.Units.JOULE;
034import static tec.units.ri.unit.Units.KELVIN;
035import static tec.units.ri.unit.Units.KILOGRAM;
036import static tec.units.ri.unit.Units.LUX;
037import static tec.units.ri.unit.Units.METRE;
038import static tec.units.ri.unit.Units.METRES_PER_SECOND;
039import static tec.units.ri.unit.Units.METRES_PER_SQUARE_SECOND;
040import static tec.units.ri.unit.Units.MOLE;
041import static tec.units.ri.unit.Units.NEWTON;
042import static tec.units.ri.unit.Units.PASCAL;
043import static tec.units.ri.unit.Units.RADIAN;
044import static tec.units.ri.unit.Units.SECOND;
045import static tec.units.ri.unit.Units.SIEVERT;
046import static tec.units.ri.unit.Units.SQUARE_METRE;
047import static tec.units.ri.unit.Units.STERADIAN;
048import static tec.units.ri.unit.Units.TESLA;
049import static tec.units.ri.unit.Units.WATT;
050import static tec.units.ri.unit.Units.WEBER;
051
052import javax.measure.Quantity;
053import javax.measure.Unit;
054import javax.measure.quantity.Acceleration;
055import javax.measure.quantity.AmountOfSubstance;
056import javax.measure.quantity.Angle;
057import javax.measure.quantity.Area;
058import javax.measure.quantity.Dimensionless;
059import javax.measure.quantity.ElectricCharge;
060import javax.measure.quantity.ElectricCurrent;
061import javax.measure.quantity.Energy;
062import javax.measure.quantity.Force;
063import javax.measure.quantity.Frequency;
064import javax.measure.quantity.Illuminance;
065import javax.measure.quantity.Length;
066import javax.measure.quantity.MagneticFlux;
067import javax.measure.quantity.MagneticFluxDensity;
068import javax.measure.quantity.Mass;
069import javax.measure.quantity.Power;
070import javax.measure.quantity.Pressure;
071import javax.measure.quantity.RadiationDoseAbsorbed;
072import javax.measure.quantity.RadiationDoseEffective;
073import javax.measure.quantity.Radioactivity;
074import javax.measure.quantity.SolidAngle;
075import javax.measure.quantity.Speed;
076import javax.measure.quantity.Temperature;
077import javax.measure.quantity.Time;
078
079//import si.uom.SI;
080//import si.uom.quantity.DynamicViscosity;
081import si.uom.quantity.IonizingRadiation;
082//import si.uom.quantity.KinematicViscosity;
083import systems.uom.quantity.Information;
084import systems.uom.quantity.Resolution;
085import tec.units.ri.AbstractSystemOfUnits;
086import tec.units.ri.AbstractUnit;
087import tec.units.ri.format.SimpleUnitFormat;
088import tec.units.ri.function.LogConverter;
089import tec.units.ri.function.RationalConverter;
090import tec.units.ri.unit.AlternateUnit;
091
092/**
093 * <p>
094 * This class contains units that are not part of the International System of
095 * Units, that is, they are outside the SI, but are important and widely used.
096 * </p>
097 * 
098 * <p>
099 * This is an internal collection of otherwise unassigned units used by
100 * <b>UCUM</b> or similar systems.
101 * </p>
102 * <p>
103 * This class is not intended to be implemented by clients.
104 * </p>
105 * 
106 * @noimplement This class is not intended to be implemented by clients.
107 * @noextend This class is not intended to be extended by clients.
108 * 
109 * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
110 * @author <a href="mailto:units@catmedia.us">Werner Keil</a>
111 * @version 1.22, $Date: 2016-09-17$
112 */
113public class NonSI extends AbstractSystemOfUnits {
114    private static final String SYSTEM_NAME = "Non-SI Units";
115    
116    /**
117     * Holds the standard gravity constant: 9.80665 m/s² exact.
118     */
119    private static final int STANDARD_GRAVITY_DIVIDEND = 980665;
120
121    private static final int STANDARD_GRAVITY_DIVISOR = 100000;
122
123    /**
124     * Holds the avoirdupois pound: 0.45359237 kg exact
125     */
126    static final int AVOIRDUPOIS_POUND_DIVIDEND = 45359237;
127
128    static final int AVOIRDUPOIS_POUND_DIVISOR = 100000000;
129
130    /**
131     * Holds the Avogadro constant.
132     */
133    private static final double AVOGADRO_CONSTANT = 6.02214199e23; // (1/mol).
134
135    /**
136     * Holds the electric charge of one electron.
137     */
138    private static final double ELEMENTARY_CHARGE = 1.602176462e-19; // (C).
139
140    /**
141     * Default constructor (prevents this class from being instantiated).
142     */
143    private NonSI() {
144    }
145
146    /**
147     * Returns the unique instance of this class.
148     * 
149     * @return the NonSI instance.
150     */
151    public static NonSI getInstance() {
152        return INSTANCE;
153    }
154
155    private static final NonSI INSTANCE = new NonSI();
156
157    // /////////////////
158    // Dimensionless //
159    // /////////////////
160    /**
161     * A dimensionless unit equals to <code>pi</code> (standard name
162     * <code>Ï€</code>).
163     */
164    static final Unit<Dimensionless> PI = addUnit(ONE.multiply(StrictMath.PI));
165
166    /**
167     * A dimensionless unit equals to <code>0.01</code> (standard name
168     * <code>%</code>).
169     */
170    // static final Unit<Dimensionless> PERCENT = addUnit(ONE
171    // .divide(100));
172
173    /**
174     * A logarithmic unit used to describe a ratio (standard name
175     * <code>dB</code>).
176     */
177    static final Unit<Dimensionless> DECIBEL = addUnit(ONE
178            .transform(new LogConverter(10).inverse().concatenate(
179                    new RationalConverter(1d, 10d))));
180
181    // ///////////////////////
182    // Amount of substance //
183    // ///////////////////////
184    /**
185     * A unit of amount of substance equals to one atom (standard name
186     * <code>atom</code>).
187     */
188    static final Unit<AmountOfSubstance> ATOM = addUnit(MOLE
189            .divide(AVOGADRO_CONSTANT));
190
191    // //////////
192    // Length //
193    // //////////
194
195    /**
196     * A unit of length equal to <code>0.3048 m</code> (standard name
197     * <code>ft</code>).
198     */
199    static final Unit<Length> FOOT = addUnit(METRE.multiply(3048).divide(10000));
200
201    /**
202     * A unit of length equal to <code>0.0254 m</code> (standard name
203     * <code>in</code>).
204     */
205    static final Unit<Length> INCH = addUnit(FOOT.divide(12));
206
207    /**
208     * A unit of length equal to <code>1E-10 m</code> (standard name
209     * <code>\u00C5ngstr\u00F6m</code>).
210     */
211    public static final Unit<Length> ANGSTROM = addUnit(METRE.divide(10000000000L));
212
213    /**
214     * A unit of length equal to the average distance from the center of the
215     * Earth to the center of the Sun (standard name <code>ua</code>).
216     */
217    static final Unit<Length> ASTRONOMICAL_UNIT = addUnit(METRE
218            .multiply(149597870691.0));
219
220    /**
221     * A unit of length equal to the distance that light travels in one year
222     * through a vacuum (standard name <code>ly</code>).
223     */
224    static final Unit<Length> LIGHT_YEAR = addUnit(METRE
225            .multiply(9.460528405e15));
226
227    /**
228     * A unit of length equal to the distance at which a star would appear to
229     * shift its position by one arcsecond over the course the time (about 3
230     * months) in which the Earth moves a distance of {@link #ASTRONOMICAL_UNIT}
231     * in the direction perpendicular to the direction to the star (standard
232     * name <code>pc</code>).
233     */
234    static final Unit<Length> PARSEC = addUnit(METRE.multiply(30856770e9));
235
236    /**
237     * A unit of length equal to <code>0.013837 {@link #INCH}</code> exactly
238     * (standard name <code>pt</code>).
239     * 
240     * @see #PIXEL
241     */
242    static final Unit<Length> POINT = addUnit(INCH.multiply(13837).divide(
243            1000000));
244
245    // ////////////
246    // Duration //
247    // ////////////
248    /**
249     * A unit of duration equal to <code>60 s</code> (standard name
250     * <code>min</code>).
251     */
252    static final Unit<Time> MINUTE = addUnit(SECOND.multiply(60));
253
254    /**
255     * A unit of duration equal to <code>60 {@link #MINUTE}</code> (standard
256     * name <code>h</code>).
257     */
258    static final Unit<Time> HOUR = addUnit(MINUTE.multiply(60));
259
260    /**
261     * A unit of duration equal to <code>24 {@link #HOUR}</code> (standard name
262     * <code>d</code>).
263     */
264    static final Unit<Time> DAY = addUnit(HOUR.multiply(24));
265
266    /**
267     * A unit of duration equal to the time required for a complete rotation of
268     * the earth in reference to any star or to the vernal equinox at the
269     * meridian, equal to 23 hours, 56 minutes, 4.09 seconds (standard name
270     * <code>day_sidereal</code>).
271     */
272    static final Unit<Time> DAY_SIDEREAL = addUnit(SECOND.multiply(86164.09));
273
274    /**
275     * A unit of duration equal to 7 {@link #DAY} (standard name
276     * <code>week</code>).
277     */
278    static final Unit<Time> WEEK = addUnit(DAY.multiply(7));
279
280    /**
281     * A unit of duration equal to 365 {@link #DAY} (standard name
282     * <code>year</code>).
283     */
284    static final Unit<Time> YEAR_CALENDAR = addUnit(DAY.multiply(365));
285
286    /**
287     * A unit of duration equal to one complete revolution of the earth about
288     * the sun, relative to the fixed stars, or 365 days, 6 hours, 9 minutes,
289     * 9.54 seconds (standard name <code>year_sidereal</code>).
290     */
291    static final Unit<Time> YEAR_SIDEREAL = addUnit(SECOND
292            .multiply(31558149.54));
293
294    /**
295     * The Julian year, as used in astronomy and other sciences, is a time unit
296     * defined as exactly 365.25 days. This is the normal meaning of the unit
297     * "year" (symbol "a" from the Latin annus, annata) used in various
298     * scientific contexts.
299     */
300    static final Unit<Time> YEAR_JULIEN = addUnit(SECOND.multiply(31557600));
301
302    // ////////
303    // Mass //
304    // ////////
305    /**
306     * A unit of mass equal to 1/12 the mass of the carbon-12 atom (standard
307     * name <code>u</code>).
308     */
309    static final Unit<Mass> ATOMIC_MASS = addUnit(KILOGRAM
310            .multiply(1e-3 / AVOGADRO_CONSTANT));
311
312    /**
313     * A unit of mass equal to the mass of the electron (standard name
314     * <code>me</code>).
315     */
316    static final Unit<Mass> ELECTRON_MASS = addUnit(KILOGRAM
317            .multiply(9.10938188e-31));
318
319    /**
320     * A unit of mass equal to <code>453.59237 grams</code> (avoirdupois pound,
321     * standard name <code>lb</code>).
322     */
323    static final Unit<Mass> POUND = addUnit(KILOGRAM.multiply(
324            AVOIRDUPOIS_POUND_DIVIDEND).divide(AVOIRDUPOIS_POUND_DIVISOR));
325
326    // ///////////////////
327    // Electric charge //
328    // ///////////////////
329    /**
330     * A unit of electric charge equal to the charge on one electron (standard
331     * name <code>e</code>).
332     */
333    static final Unit<ElectricCharge> E = addUnit(COULOMB
334            .multiply(ELEMENTARY_CHARGE));
335
336    /**
337     * A unit of electric charge equal to equal to the product of Avogadro's
338     * number (see {@link SI#MOLE}) and the charge (1 e) on a single electron
339     * (standard name <code>Fd</code>).
340     */
341    static final Unit<ElectricCharge> FARADAY = addUnit(COULOMB
342            .multiply(ELEMENTARY_CHARGE * AVOGADRO_CONSTANT)); // e/mol
343
344    /**
345     * A unit of electric charge which exerts a force of one dyne on an equal
346     * charge at a distance of one centimeter (standard name <code>Fr</code>).
347     */
348    static final Unit<ElectricCharge> FRANKLIN = addUnit(COULOMB
349            .multiply(3.3356e-10));
350
351    // ///////////////
352    // Temperature //
353    // ///////////////
354    /**
355     * A unit of temperature equal to <code>5/9 °K</code> (standard name
356     * <code>°R</code>).
357     */
358    static final Unit<Temperature> RANKINE = addUnit(KELVIN.multiply(5).divide(
359            9));
360
361    // /////////
362    // Angle //
363    // /////////
364
365    /**
366     * A unit of angle equal to a full circle or <code>2<i>&pi;</i>
367     * {@link SI#RADIAN}</code> (standard name <code>rev</code>).
368     */
369    static final Unit<Angle> REVOLUTION = addUnit(RADIAN.multiply(2)
370            .multiply(Math.PI).asType(Angle.class));
371
372    // ////////////
373    // Velocity //
374    // ////////////
375    /**
376     * A unit of velocity relative to the speed of light (standard name
377     * <code>c</code>).
378     */
379    static final Unit<Speed> C = addUnit(METRES_PER_SECOND.multiply(299792458));
380
381    // ////////////////
382    // Acceleration //
383    // ////////////////
384    /**
385     * A unit of acceleration equal to the gravity at the earth's surface
386     * (standard name <code>grav</code>).
387     */
388    static final Unit<Acceleration> G = addUnit(METRES_PER_SQUARE_SECOND
389            .multiply(STANDARD_GRAVITY_DIVIDEND).divide(
390                    STANDARD_GRAVITY_DIVISOR));
391
392    // ////////
393    // Area //
394    // ////////
395    /**
396     * A unit of area equal to <code>100 m²</code> (standard name <code>a</code>
397     * ).
398     */
399    static final Unit<Area> ARE = addUnit(SQUARE_METRE.multiply(100));
400
401    // ///////////////
402    // Information //
403    // ///////////////
404    /**
405     * The unit for binary information (standard name <code>bit</code>).
406     */
407    static final Unit<Information> BIT = addUnit(
408            new AlternateUnit<Information>(ONE, "bit"), Information.class);
409
410    /**
411     * A unit of data amount equal to <code>8 {@link SI#BIT}</code> (BinarY
412     * TErm, standard name <code>byte</code>).
413     */
414    private static final Unit<Information> BYTE = addUnit(BIT.multiply(8));
415
416    /**
417     * The SI unit for binary information rate (standard name <code>bit/s</code>
418     * ).
419     * 
420     * @deprecated see https://java.net/jira/browse/UNITSOFMEASUREMENT-100
421     */
422//    private static final ProductUnit<InformationRate> BITS_PER_SECOND = addUnit(
423//          new ProductUnit<InformationRate>(BIT.divide(SECOND)),
424//          InformationRate.class);
425
426    /**
427     * Equivalent {@link #BYTE}
428     */
429    static final Unit<Information> OCTET = BYTE;
430
431    /**
432     * A pixel has 4 channels which define transparency (alpha), red, green and
433     * blue color values. Each channel is one byte wide.
434     * 
435     * @see #BYTE
436     */
437    static final Unit<Information> PIXEL = addUnit(BYTE.multiply(4.0));
438
439    /**
440     * Pixel per inch describe the resolution for any output device (monitor,
441     * printer) that deals with outputting digital raster images.
442     * 
443     * @see #INCH
444     * @see #PIXEL
445     */
446    static final Unit<Resolution> PIXEL_PER_INCH = addUnit(PIXEL.divide(INCH)
447            .asType(Resolution.class));
448
449    /**
450     * Equivalent {@link #PIXEL}
451     */
452    static final Unit<Information> COMPUTER_POINT = PIXEL;
453
454    // ////////////////////
455    // Electric current //
456    // ////////////////////
457    /**
458     * A unit of electric charge equal to the centimeter-gram-second
459     * electromagnetic unit of magnetomotive force, equal to <code>10/4
460     * &pi;ampere-turn</code> (standard name <code>Gi</code>).
461     */
462    static final Unit<ElectricCurrent> GILBERT = addUnit(AMPERE.multiply(10)
463            .divide(4).multiply(PI).asType(ElectricCurrent.class));
464
465    // //////////
466    // Energy //
467    // //////////
468    /**
469     * A unit of energy equal to <code>1E-7 J</code> (standard name
470     * <code>erg</code>).
471     */
472    static final Unit<Energy> ERG = addUnit(JOULE.divide(10000000));
473
474    /**
475     * A unit of energy equal to one electron-volt (standard name
476     * <code>eV</code>, also recognized <code>keV, MeV, GeV</code>).
477     */
478    static final Unit<Energy> ELECTRON_VOLT = addUnit(JOULE
479            .multiply(ELEMENTARY_CHARGE));
480
481    // ///////////////
482    // Illuminance //
483    // ///////////////
484    /**
485     * A unit of illuminance equal to <code>1E4 Lx</code> (standard name
486     * <code>La</code>).
487     */
488    static final Unit<Illuminance> LAMBERT = addUnit(LUX.multiply(10000));
489
490    // /////////////////
491    // Magnetic Flux //
492    // /////////////////
493    /**
494     * A unit of magnetic flux equal <code>1E-8 Wb</code> (standard name
495     * <code>Mx</code>).
496     */
497    static final Unit<MagneticFlux> MAXWELL = addUnit(WEBER.divide(100000000));
498
499    // /////////////////////////
500    // Magnetic Flux Density //
501    // /////////////////////////
502    /**
503     * A unit of magnetic flux density equal <code>1000 A/m</code> (standard
504     * name <code>G</code>).
505     */
506    static final Unit<MagneticFluxDensity> GAUSS = addUnit(TESLA.divide(10000));
507
508    // /////////
509    // Force //
510    // /////////
511    /**
512     * A unit of force equal to <code>1E-5 N</code> (standard name
513     * <code>dyn</code>).
514     */
515    static final Unit<Force> DYNE = addUnit(NEWTON.divide(100000));
516
517    /**
518     * A unit of force equal to <code>9.80665 N</code> (standard name
519     * <code>kgf</code>).
520     */
521    static final Unit<Force> KILOGRAM_FORCE = addUnit(NEWTON.multiply(
522            STANDARD_GRAVITY_DIVIDEND).divide(STANDARD_GRAVITY_DIVISOR));
523
524    /**
525     * A unit of force equal to <code>{@link #POUND}·{@link #G}</code>
526     * (standard name <code>lbf</code>).
527     */
528    static final Unit<Force> POUND_FORCE = addUnit(NEWTON.multiply(
529            1L * AVOIRDUPOIS_POUND_DIVIDEND * STANDARD_GRAVITY_DIVIDEND)
530            .divide(1L * AVOIRDUPOIS_POUND_DIVISOR * STANDARD_GRAVITY_DIVISOR));
531
532    // /////////
533    // Power //
534    // /////////
535    /**
536     * A unit of power equal to the power required to raise a mass of 75
537     * kilograms at a velocity of 1 meter per second (metric, standard name
538     * <code>hp</code>).
539     */
540    static final Unit<Power> HORSEPOWER = addUnit(WATT.multiply(735.499));
541
542    // ////////////
543    // Pressure //
544    // ////////////
545    /**
546     * A unit of pressure equal to the average pressure of the Earth's
547     * atmosphere at sea level (standard name <code>atm</code>).
548     */
549    static final Unit<Pressure> ATMOSPHERE = addUnit(PASCAL.multiply(101325));
550
551    /**
552     * A unit of pressure equal to <code>100 kPa</code> (standard name
553     * <code>bar</code>).
554     */
555    public static final Unit<Pressure> BAR = addUnit(PASCAL.multiply(100000));
556
557    /**
558     * A unit of pressure equal to the pressure exerted at the Earth's surface
559     * by a column of mercury 1 millimeter high (standard name <code>mmHg</code>
560     * ).
561     */
562    static final Unit<Pressure> MILLIMETRE_OF_MERCURY = addUnit(PASCAL
563            .multiply(133.322));
564
565    /**
566     * A unit of pressure equal to the pressure exerted at the Earth's surface
567     * by a column of mercury 1 inch high (standard name <code>inHg</code>).
568     */
569    static final Unit<Pressure> INCH_OF_MERCURY = addUnit(PASCAL
570            .multiply(3386.388));
571
572    // ///////////////////////////
573    // Radiation dose absorbed //
574    // ///////////////////////////
575    /**
576     * A unit of radiation dose absorbed equal to a dose of 0.01 joule of energy
577     * per kilogram of mass (J/kg) (standard name <code>rd</code>).
578     */
579    public static final Unit<RadiationDoseAbsorbed> RAD = addUnit(GRAY.divide(100));
580
581    /**
582     * A unit of radiation dose effective equal to <code>0.01 Sv</code>
583     * (standard name <code>rem</code>).
584     */
585    static final Unit<RadiationDoseEffective> REM = addUnit(SIEVERT.divide(100));
586
587    // ////////////////////////
588    // Radioactive activity //
589    // ////////////////////////
590    /**
591     * A unit of radioctive activity equal to the activity of a gram of radium
592     * (standard name <code>Ci</code>).
593     */
594    static final Unit<Radioactivity> CURIE = addUnit(BECQUEREL
595            .multiply(37000000000L));
596
597    /**
598     * A unit of radioctive activity equal to 1 million radioactive
599     * disintegrations per second (standard name <code>Rd</code>).
600     */
601    static final Unit<Radioactivity> RUTHERFORD = addUnit(BECQUEREL
602            .multiply(1000000));
603
604    // ///////////////
605    // Solid angle //
606    // ///////////////
607    /**
608     * A unit of solid angle equal to <code>4 <i>&pi;</i> steradians</code>
609     * (standard name <code>sphere</code>).
610     */
611    static final Unit<SolidAngle> SPHERE = addUnit(STERADIAN.multiply(4)
612            .multiply(PI).asType(SolidAngle.class));
613
614    // //////////
615    // Volume //
616    // //////////
617
618    // /////////////
619    // Viscosity //
620    // /////////////
621    /**
622     * A unit of dynamic viscosity equal to <code>1 g/(cm·s)</code> (cgs unit).
623     */
624//    static final Unit<DynamicViscosity> POISE = addUnit(
625//          GRAM.divide(CENTI(METRE).multiply(SECOND))).asType(
626//          DynamicViscosity.class);
627// FIXME move to CGS module, see https://de.wikipedia.org/wiki/Poise
628    /**
629     * A unit of kinematic viscosity equal to <code>1 cm²/s</code> (cgs unit).
630     */
631//    static final Unit<KinematicViscosity> STOKES = addUnit(
632//          CENTI(METRE).pow(2).divide(SECOND))
633//          .asType(KinematicViscosity.class);
634// FIXME move to CGS module
635    
636    // /////////////
637    // Frequency //
638    // /////////////
639    /**
640     * A unit used to measure the frequency (rate) at which an imaging device
641     * produces unique consecutive images (standard name <code>fps</code>).
642     */
643    static final Unit<Frequency> FRAMES_PER_SECOND = addUnit(ONE.divide(SECOND))
644            .asType(Frequency.class);
645
646    // //////////
647    // Others //
648    // //////////
649    /**
650     * A unit used to measure the ionizing ability of radiation (standard name
651     * <code>Roentgen</code>).
652     */
653    // static final Unit<IonizingRadiation> ROENTGEN = SI.ROENTGEN;
654
655    /**
656     * A unit used to measure the ionizing ability of radiation (standard name
657     * <code>Roentgen</code>).
658     */
659    @SuppressWarnings("unchecked")
660    public static final Unit<IonizingRadiation> ROENTGEN = (Unit<IonizingRadiation>)
661            addUnit(COULOMB.divide(KILOGRAM).multiply(2.58e-4), "Roentgen", "r", true);
662
663    public String getName() {
664        return SYSTEM_NAME;
665    }
666
667    /**
668     * Adds a new unit not mapped to any specified quantity type.
669     *
670     * @param unit
671     *            the unit being added.
672     * @return <code>unit</code>.
673     */
674    private static <U extends Unit<?>> U addUnit(U unit) {
675        INSTANCE.units.add(unit);
676        return unit;
677    }
678
679    /**
680     * Adds a new unit and maps it to the specified quantity type.
681     *
682     * @param unit
683     *            the unit being added.
684     * @param type
685     *            the quantity type.
686     * @return <code>unit</code>.
687     */
688    private static <U extends AbstractUnit<?>> U addUnit(U unit,
689            Class<? extends Quantity<?>> type) {
690        INSTANCE.units.add(unit);
691        INSTANCE.quantityToUnit.put(type, unit);
692        return unit;
693    }
694
695    /**
696     * Adds a new unit not mapped to any specified quantity type and puts a text
697     * as symbol or label.
698     *
699     * @param unit
700     *            the unit being added.
701     * @param name
702     *            the string to use as name
703     * @param text
704     *            the string to use as label or symbol
705     * @param isLabel
706     *            if the string should be used as a label or not
707     * @return <code>unit</code>.
708     */
709    private static <U extends Unit<?>> U addUnit(U unit, String name,
710            String text, boolean isLabel) {
711        if (isLabel && text != null) {
712            SimpleUnitFormat.getInstance().label(unit, text);
713        }
714        if (name != null && unit instanceof AbstractUnit) {
715            return Helper.addUnit(INSTANCE.units, unit, name);
716        } else {
717            INSTANCE.units.add(unit);
718        }
719        return unit;
720    }
721}