/*
* Copyright 1999, University Corporation for Atmospheric Research
* See file LICENSE for copying and redistribution conditions.
*
* $Id: DefaultUnitsDB.java,v 1.9 2010-05-19 12:29:03 donm Exp $
*/
package visad.data.units;
import visad.BaseUnit;
import visad.OffsetUnit;
import visad.SI;
import visad.ScaledUnit;
import visad.Unit;
import visad.UnitException;
/**
* Default units database.
*
* This database knows about approximately 500 different units. Users can also
* add new units to the database at runtime.
*
* The basis for this units database is the International System of Units (SI).
*
* This is a singleton class.
*/
public final class DefaultUnitsDB extends UnitTable {
/**
* The singleton instance of this class.
*/
private static final DefaultUnitsDB db;
static {
try {
db = new DefaultUnitsDB();
}
catch (UnitException e) {
throw (ExceptionInInitializerError) new ExceptionInInitializerError().initCause(e);
}
}
/**
* The unit prefix names in order of lexicographic length:
*/
protected final UnitPrefix[] prefixNames = {
new UnitPrefix("centi", 1e-2),
new UnitPrefix("femto", 1e-15),
new UnitPrefix("hecto", 1e2),
new UnitPrefix("micro", 1e-6),
new UnitPrefix("milli", 1e-3),
new UnitPrefix("yocto", 1e-24),
new UnitPrefix("yotta", 1e24),
new UnitPrefix("zepto", 1e-21),
new UnitPrefix("zetta", 1e21),
new UnitPrefix("atto", 1e-18),
new UnitPrefix("deca", 1e1), // Spelling according to "ISO 2955:
// Information processing --
// Representation of SI and other units
// in systems with limited character
// sets"
new UnitPrefix("deci", 1e-1),
new UnitPrefix("deka", 1e1), // Spelling according to "ASTM
// Designation: E 380 - 85: Standard
// for METRIC PRACTICE", "ANSI/IEEE Std
// 260-1978 (Reaffirmed 1985): IEEE
// Standard Letter Symbols for Units of
// Measurement", and NIST Special
// Publication 811, 1995 Edition:
// "Guide for the Use of the
// International System of Units (SI)".
new UnitPrefix("giga", 1e9), // 1st syllable pronounced "jig"
// according to "ASTM Designation: E
// 380 - 85: Standard for METRIC
// PRACTICE".
new UnitPrefix("kilo", 1e3), new UnitPrefix("mega", 1e6),
new UnitPrefix("nano", 1e-9), new UnitPrefix("peta", 1e15),
new UnitPrefix("pico", 1e-12), new UnitPrefix("tera", 1e12),
new UnitPrefix("exa", 1e18), };
/**
* The unit prefix symbols in order of lexicographic length:
*/
protected final UnitPrefix[] prefixSymbols = {
new UnitPrefix("da", 1e1), new UnitPrefix("E", 1e18),
new UnitPrefix("G", 1e9), new UnitPrefix("M", 1e6),
new UnitPrefix("P", 1e15), new UnitPrefix("T", 1e12),
new UnitPrefix("Y", 1e24), new UnitPrefix("Z", 1e21),
new UnitPrefix("a", 1e-18), new UnitPrefix("c", 1e-2),
new UnitPrefix("d", 1e-1), new UnitPrefix("f", 1e-15),
new UnitPrefix("h", 1e2), new UnitPrefix("k", 1e3),
new UnitPrefix("m", 1e-3), new UnitPrefix("n", 1e-9),
new UnitPrefix("p", 1e-12), new UnitPrefix("u", 1e-6),
new UnitPrefix("y", 1e-24), new UnitPrefix("z", 1e-21), };
/**
* Constructs a default, units database.
*
* @throws UnitException
* Something went wrong in generating a unit for the database.
* This should not occur and indicates an internal
* inconsistancy.
*/
private DefaultUnitsDB() throws UnitException {
/*
* Create a unit table of the proper size. Because increasing the size
* might be expensive, the initial size should be kept in sync with the
* actual number of entries (e.g. in vi: :.,$w !egrep 'pn\(' | wc -l
* (times 2 plus) :.,$w !egrep '(put|px)\(' | wc -l :.,$w !egrep 'ps\('
* | wc -l
*/
super(677, 98);
/*
* The base units:
*/
put(SI.ampere);
put(SI.candela);
put(SI.kelvin);
put(SI.kilogram);
put(SI.meter);
put(SI.mole);
put(SI.second);
put(SI.radian);
put(SI.steradian);
/*
* Constants:
*/
ps("%", new ScaledUnit(0.01));
pn("percent", "%");
pn("PI", new ScaledUnit(Math.PI));
pn("bakersdozen", new ScaledUnit(13));
pn("pair", new ScaledUnit(2));
pn("ten", new ScaledUnit(10));
pn("dozen", new ScaledUnit(12));
pn("score", new ScaledUnit(20));
pn("hundred", new ScaledUnit(100));
pn("thousand", new ScaledUnit(1.0e3));
pn("million", new ScaledUnit(1.0e6));
// NB: "billion" is ambiguous (1e9 in U.S. but 1e12 in U.K.)
/*
* NB: All subsequent definitions must be given in terms of earlier
* definitions. Forward referencing is not permitted.
*/
/*
* The following are non-base units of the fundamental quantities
*/
/*
* UNITS OF ELECTRIC CURRENT
*/
pn("amp", "ampere");
pn("abampere", get("A").scale(10)); // exact
pn("gilbert", get("A").scale(7.957747e-1));
pn("statampere", get("A").scale(3.335640e-10));
pn("biot", "abampere");
/*
* UNITS OF LUMINOUS INTENSITY
*/
pn("candle", "candela");
/*
* UNITS OF THERMODYNAMIC TEMPERATURE
*/
px("degree kelvin", "K");
px("degrees kelvin", "K");
ps("degK", "K");
px("degreeK", "K");
px("degreesK", "K");
px("deg K", "K");
px("degree K", "K");
px("degrees K", "K");
ps("°C", new OffsetUnit(273.15, (BaseUnit) get("K")));
pn("celsius", "°C");
px("degree celsius", "°C");
px("degrees celsius", "°C");
pn("centigrade", "°C");
px("degree centigrade", "°C");
px("degrees centigrade", "°C");
px("degC", "°C");
px("degreeC", "°C");
px("degreesC", "°C");
px("deg C", "°C");
px("degree C", "°C");
px("degrees C", "°C");
px("Cel", "°C");
// ps("C", "Cel"); // `C' means `coulomb'
pn("rankine", get("K").scale(1 / 1.8));
px("degree rankine", "rankine");
px("degrees rankine", "rankine");
px("degR", "rankine");
px("degreeR", "rankine");
px("degreesR", "rankine");
px("deg R", "rankine");
px("degree R", "rankine");
px("degrees R", "rankine");
// ps("R", "rankine"); // "R" means "roentgen"
pn("°F", get("Rankine").shift(459.67));
px("fahrenheit", "°F");
px("degree fahrenheit", "°F");
px("degrees fahrenheit", "°F");
px("degF", "°F");
px("degreeF", "°F");
px("degreesF", "°F");
px("deg F", "°F");
px("degree F", "°F");
px("degrees F", "°F");
// ps("F", "fahrenheit"); // "F" means "farad"
/*
* UNITS OF MASS
*/
pn("assay ton", get("kg").scale(2.916667e-2));
pn("avoirdupois ounce", get("kg").scale(2.834952e-2));
pn("avoirdupois pound", get("kg").scale(4.5359237e-1)); // exact
pn("carat", get("kg").scale(2e-4));
ps("gr", get("kg").scale(6.479891e-5)); // exact
ps("g", get("kg").scale(1e-3)); // exact
pn("long hundredweight", get("kg").scale(5.080235e1));
ps("tne", get("kg").scale(1e3)); // exact
pn("pennyweight", get("kg").scale(1.555174e-3));
pn("short hundredweight", get("kg").scale(4.535924e1));
pn("slug", get("kg").scale(14.59390));
pn("troy ounce", get("kg").scale(3.110348e-2));
pn("troy pound", get("kg").scale(3.732417e-1));
pn("amu", get("kg").scale(1.66054e-27));
pn("scruple", get("gr").scale(20));
pn("apdram", get("gr").scale(60));
pn("apounce", get("gr").scale(480));
pn("appound", get("gr").scale(5760));
pn("gram", "g"); // was "gravity"
pn("tonne", "tne");
px("metric ton", "tne");
pn("apothecary ounce", "troy ounce");
pn("apothecary pound", "troy pound");
pn("pound", "avoirdupois pound");
pn("metricton", "tne");
ps("grain", "gr");
pn("atomicmassunit", "amu");
pn("atomic mass unit", "amu");
ps("t", "tne");
ps("lb", "avoirdupois pound");
pn("bag", get("pound").scale(94));
pn("short ton", get("pound").scale(2000));
pn("long ton", get("pound").scale(2240));
pn("ton", "short ton");
pn("shortton", "short ton");
pn("longton", "long ton");
/*
* UNITS OF LENGTH
*/
pn("angstrom", get("m").scale(1e-10));
pn("au", get("m").scale(1.495979e11));
pn("fermi", get("m").scale(1e-15)); // exact
pn("light year", get("m").scale(9.46073e15));
pn("micron", get("m").scale(1e-6)); // exact
pn("mil", get("m").scale(2.54e-5)); // exact
pn("nautical mile", get("m").scale(1.852000e3)); // exact
pn("parsec", get("m").scale(3.085678e16));
pn("printers point", get("m").scale(3.514598e-4));
pn("metre", "m");
px("prs", "parsec");
/*
* God help us! There's an international foot and a US survey foot and
* they're not the same!
*/
// US Survey foot stuff:
px("US survey foot", get("m").scale(1200 / 3937.)); // exact
pn("US survey yard", get("US survey foot").scale(3)); // exact
pn("US survey mile", get("US survey foot").scale(5280)); // exact
pn("rod", get("US survey foot").scale(16.5)); // exact
pn("furlong", get("US survey foot").scale(660)); // exact
pn("fathom", get("US survey foot").scale(6)); // exact
px("US survey feet", "US survey foot");
pn("US statute mile", "US survey mile");
pn("pole", "rod");
px("perch", "rod");
px("perches", "perch");
// International foot stuff:
px("international inch", get("m").scale(.0254)); // exact
px("international foot", get("international inch").scale(12));
// exact
pn("international yard", get("international foot").scale(3));
// exact
pn("international mile", get("international foot").scale(5280));
// exact
px("international inches", "international inch"); // alias
px("international feet", "international foot"); // alias
// Alias unspecified units to the international units:
px("inch", "international inch"); // alias
px("foot", "international foot"); // alias
pn("yard", "international yard"); // alias
pn("mile", "international mile"); // alias
// The following should hold regardless:
px("inches", "inch"); // alias
ps("in", "inches"); // alias
px("feet", "foot"); // alias
ps("ft", "feet"); // alias
ps("yd", "yard"); // alias
ps("mi", "mile"); // alias
pn("chain", get("m").scale(2.011684e1));
pn("pica", get("printers point").scale(12)); // exact
pn("printers pica", "pica");
pn("astronomicalunit", "au");
ps("astronomical unit", "au");
px("asu", "au");
pn("nmile", "nautical mile");
ps("nmi", "nautical mile");
pn("big point", get("inch").scale(1. / 72)); // exact
pn("barleycorn", get("inch").scale(1. / 3));
pn("arpentlin", get("foot").scale(191.835));
// The following is for Ozone measurements:
pn("Dobson", get("m").scale(.00001)); // exact
pn("DU", "Dobson");
/*
* UNITS OF TIME
*/
/*
* Interval between 2 successive passages of sun through vernal equinox
* (365.242198781 days -- see
* http://www.ast.cam.ac.uk/pubinfo/leaflets/,
* http://aa.usno.navy.mil/AA/ and
* http://adswww.colorado.edu/adswww/astro coord.html):
*/
pn("year", get("s").scale(3.15569259747e7));
ps("d", get("s").scale(8.64e4)); // exact
ps("h", get("s").scale(3.6e3)); // exact
ps("min", get("s").scale(60)); // exact
pn("shake", get("s").scale(1e-8)); // exact
pn("sidereal day", get("s").scale(8.616409e4));
pn("sidereal hour", get("s").scale(3.590170e3));
pn("sidereal minute", get("s").scale(5.983617e1));
pn("sidereal second", get("s").scale(0.9972696));
pn("sidereal year", get("s").scale(3.155815e7));
pn("day", "d");
pn("hour", "h");
pn("minute", "min");
pn("sec", "s"); // avoid
pn("lunar month", get("d").scale(29.530589));
pn("common year", get("d").scale(365));
// exact: 153600e7 seconds
pn("leap year", get("d").scale(366)); // exact
pn("Julian year", get("d").scale(365.25)); // exact
pn("Gregorian year", get("d").scale(365.2425)); // exact
pn("tropical year", "year");
pn("sidereal month", get("d").scale(27.321661));
pn("tropical month", get("d").scale(27.321582));
pn("fortnight", get("d").scale(14));
pn("week", get("d").scale(7)); // exact
pn("jiffy", get("s").scale(1e-2)); // it's true
pn("eon", get("year").scale(1e9)); // fuzzy
pn("month", get("year").scale(1. / 12)); // on average
pn("tropical year", "year");
pn("yr", "year");
ps("a", "year"); // "anno"
px("ann", "year"); // "anno"
pn("hr", "h");
/*
* UNITS OF PLANE ANGLE
*/
pn("circle", get("radian").scale(2 * Math.PI));
pn("deg", get("radian").scale(Math.PI / 180.));
pn("'", get("deg").scale(1. / 60));
pn("\"", get("deg").scale(1. / 3600));
pn("grade", get("deg").scale(0.9)); // exact
pn("cycle", get("circle"));
pn("turn", "circle");
pn("revolution", "cycle");
px("gon", "grade");
pn("angular degree", "deg");
pn("angular minute", "'");
pn("angular second", "\"");
pn("arcdeg", "deg");
pn("degree", "deg");
pn("arcminute", "'");
px("mnt", "'");
pn("arcsecond", "\"");
// px("sec", "\""); // avoid
pn("arcmin", "'");
pn("arcsec", "\"");
px("degree true", get("deg"));
px("degrees true", get("deg"));
px("degrees north", get("deg"));
px("degrees east", get("deg"));
px("degrees south", get("degrees north").scale(-1));
px("degrees west", get("degrees east").scale(-1));
px("degree north", "degrees north");
px("degreeN", "degrees north");
px("degree N", "degrees north");
px("degreesN", "degrees north");
px("degrees N", "degrees north");
px("degree east", "degrees east");
px("degreeE", "degrees east");
px("degree E", "degrees east");
px("degreesE", "degrees east");
px("degrees E", "degrees east");
px("degree west", "degrees west");
px("degreeW", "degrees west");
px("degree W", "degrees west");
px("degreesW", "degrees west");
px("degrees W", "degrees west");
px("degree true", "degrees true");
px("degreeT", "degrees true");
px("degree T", "degrees true");
px("degreesT", "degrees true");
px("degrees T", "degrees true");
/*
* The following are derived units with special names. They are useful
* for defining other derived units.
*/
ps("Hz", get("second").pow(-1));
ps("N", get("kg").multiply(get("m").divide(get("s").pow(2))));
ps("C", get("A").multiply(get("s")));
ps("lm", get("cd").multiply(get("sr")));
ps("Bq", get("Hz"));
// SI unit of activity of a radionuclide
px("standard free fall", get("m").divide(get("s").pow(2)).scale(
9.806650));
ps("Pa", get("N").divide(get("m").pow(2)));
ps("J", get("N").multiply(get("m")));
ps("lx", get("lm").divide(get("m").pow(2)));
pn("sphere", get("steradian").scale(4 * Math.PI));
ps("W", get("J").divide(get("s")));
ps("Gy", get("J").divide(get("kg")));
// absorbed dose. derived unit
ps("Sv", get("J").divide(get("kg")));
// dose equivalent. derived unit
ps("V", get("W").divide(get("A")));
ps("F", get("C").divide(get("V")));
ps("Ohm", get("V").divide(get("A")));
ps("S", get("A").divide(get("V")));
ps("Wb", get("V").multiply(get("s")));
ps("T", get("Wb").divide(get("m").pow(2)));
ps("H", get("Wb").divide(get("A")));
pn("newton", "N");
pn("hertz", "Hz");
pn("watt", "W");
px("force", "standard free fall");
px("gravity", "standard free fall");
px("free fall", "standard free fall");
px("conventional mercury", get("gravity").multiply(
get("kg").divide(get("m").pow(3))).scale(13595.10));
px("mercury 0C", get("gravity").multiply(
get("kg").divide(get("m").pow(3))).scale(13595.1));
px("mercury 60F", get("gravity").multiply(
get("kg").divide(get("m").pow(3))).scale(13556.8));
px("conventional water", get("gravity").multiply(
get("kg").divide(get("m").pow(3))).scale(1000)); // exact
px("water 4C", get("gravity").multiply(
get("kg").divide(get("m").pow(3))).scale(999.972));
px("water 60F", get("gravity").multiply(
get("kg").divide(get("m").pow(3))).scale(999.001));
// ps("g", get("gravity"))); // approx. should be `local'.
// avoid.
px("mercury 32F", "mercury 0C");
px("water 39F", "water 4C"); // actually 39.2 degF
px("mercury", "conventional mercury");
px("water", "conventional water");
pn("farad", "F");
ps("Hg", "mercury");
px("H2O", "water");
/*
* The following are compound units: units whose definitions consist of
* two or more base units. They may now be defined in terms of the
* preceding units.
*/
/*
* ACCELERATION
*/
ps("Gal", get("m").divide(get("s").pow(2)).scale(1e-2));
// avoid "gal" (gallon)
px("gals", "Gal"); // avoid "gal" (gallon)
/*
* AREA
*/
pn("are", get("m").pow(2).scale(1e2)); // exact
pn("barn", get("m").pow(2).scale(1e-28)); // exact
pn("circular mil", get("m").pow(2).scale(5.067075e-10));
pn("darcy", get("m").pow(2).scale(9.869233e-13)); // permeability of
// porous solids
pn("hectare", get("hectoare")); // exact
px("har", "hectare"); // exact
pn("acre", get("rod").pow(2).scale(160)); // exact
ps("b", get("barn"));
/*
* ELECTRICITY AND MAGNETISM
*/
pn("abfarad", get("F").scale(1e9)); // exact
pn("abhenry", get("H").scale(1e-9)); // exact
pn("abmho", get("S").scale(1e9)); // exact
pn("abohm", get("Ohm").scale(1e-9)); // exact
pn("megohm", get("Ohm").scale(1e6)); // exact
pn("kilohm", get("Ohm").scale(1e3)); // exact
pn("abvolt", get("V").scale(1e-8)); // exact
ps("e", get("C").scale(1.60217733 - 19));
pn("chemical faraday", get("C").scale(9.64957e4));
pn("physical faraday", get("C").scale(9.65219e4));
pn("C12 faraday", get("C").scale(9.648531e4));
pn("gamma", get("nT")); // exact
pn("gauss", get("T").scale(1e-4)); // exact
pn("maxwell", get("Wb").scale(1e-8)); // exact
ps("Oe", get("A").divide(get("m")).scale(7.957747e1));
pn("statcoulomb", get("C").scale(3.335640e-10));
pn("statfarad", get("F").scale(1.112650e-12));
pn("stathenry", get("H").scale(8.987554e11));
pn("statmho", get("S").scale(1.112650e-12));
pn("statohm", get("Ohm").scale(8.987554e11));
pn("statvolt", get("V").scale(2.997925e2));
pn("unit pole", get("Wb").scale(1.256637e-7));
pn("henry", "H");
pn("siemens", "S");
pn("ohm", "Ohm");
pn("tesla", "T");
pn("volt", "V");
pn("weber", "Wb");
pn("mho", "siemens");
pn("oersted", "Oe");
pn("faraday", "C12 faraday"); // charge of 1 mole of electrons
pn("coulomb", "C");
/*
* ENERGY (INCLUDES WORK)
*/
ps("eV", get("J").scale(1.602177e-19));
ps("bev", get("eV").scale(1e9));
pn("erg", get("J").scale(1e-7)); // exact
pn("IT Btu", get("J").scale(1.05505585262e3)); // exact
pn("EC therm", get("J").scale(1.05506e8)); // exact
pn("thermochemical calorie", get("J").scale(4.184000)); // exact
pn("IT calorie", get("J").scale(4.1868)); // exact
px("ton TNT", get("J").scale(4.184e9));
pn("US therm", get("J").scale(1.054804e8)); // exact
ps("Wh", get("W").multiply(get("h")));
pn("joule", "J");
pn("therm", "US therm");
pn("watthour", "Wh");
ps("Btu", "IT Btu");
pn("calorie", "IT calorie");
pn("electronvolt", "eV");
pn("electron volt", "eV");
ps("thm", "therm");
ps("cal", "calorie");
/*
* FORCE
*/
pn("dyne", get("N").scale(1e-5)); // exact
pn("pond", get("N").scale(9.806650e-3)); // exact
px("force kilogram", get("N").scale(9.806650)); // exact
px("force gram", get("N").scale(9.806650e-3)); // exact
px("force ounce", get("N").scale(2.780139e-1));
px("force pound", get("N").scale(4.4482216152605)); // exact
pn("poundal", get("N").scale(1.382550e-1));
pn("force ton", get("force pound").scale(2000)); // exact
ps("gf", "force gram");
ps("lbf", "force pound");
px("ounce force", "force ounce");
px("kilogram force", "force kilogram");
px("pound force", "force pound");
ps("ozf", "force ounce");
ps("kgf", "force kilogram");
px("ton force", "force ton");
px("gram force", "force gram");
pn("kip", get("lbf").scale(1e3));
/*
* HEAT
*/
pn("clo", get("K").multiply(get("m").pow(2).divide(get("W"))).scale(
1.55e-1));
/*
* LIGHT
*/
pn("lumen", "lm");
pn("lux", "lx");
pn("footcandle", get("lux").scale(1.076391e-1));
pn("footlambert", get("cd").divide(get("m").pow(2)).scale(3.426259));
pn("lambert", get("cd").divide(get("m").pow(2)).scale(1e4 / Math.PI)); // exact
pn("stilb", get("cd").divide(get("m").pow(2)).scale(1e4));
pn("phot", get("lm").divide(get("m").pow(2)).scale(1e4)); // exact
pn("nit", get("cd").multiply(get("m").pow(2))); // exact
pn("langley", get("J").divide(get("m").pow(2)).scale(4.184000e4)); // exact
pn("blondel", get("cd").divide(get("m").pow(2)).scale(1. / Math.PI));
pn("apostilb", "blondel");
ps("nt", "nit");
ps("ph", "phot");
ps("sb", "stilb");
/*
* MASS PER UNIT LENGTH
*/
pn("denier", get("kg").divide(get("m")).scale(1.111111e-7));
pn("tex", get("kg").divide(get("m")).scale(1e-6));
/*
* MASS PER UNIT TIME (INCLUDES FLOW)
*/
px("perm 0C", get("kg").divide(
get("Pa").multiply(get("s")).multiply(get("m").pow(2))).scale(
5.72135e-11));
px("perm 23C", get("kg").divide(
get("Pa").multiply(get("s")).multiply(get("m").pow(2))).scale(
5.74525e-11));
/*
* POWER
*/
ps("VA", get("V").multiply(get("A")));
pn("voltampere", "VA");
pn("boiler horsepower", get("W").scale(9.80950e3));
pn("shaft horsepower", get("W").scale(7.456999e2));
pn("metric horsepower", get("W").scale(7.35499));
pn("electric horsepower", get("W").scale(7.460000e2)); // exact
pn("water horsepower", get("W").scale(7.46043e2));
pn("UK horsepower", get("W").scale(7.4570e2));
pn("refrigeration ton", get("Btu").divide(get("h")).scale(12000));
pn("horsepower", "shaft horsepower");
pn("ton of refrigeration", "refrigeration ton");
ps("hp", "horsepower");
/*
* PRESSURE OR STRESS
*/
pn("bar", get("Pa").scale(1e5)); // exact
pn("standard atmosphere", get("Pa").scale(1.01325e5)); // exact
pn("technical atmosphere", get("kg").multiply(
get("gravity").divide(get("m").scale(.01).pow(2))));
px("inch H2O 39F", get("inch").multiply(get("water 39F")));
px("inch H2O 60F", get("inch").multiply(get("water 60F")));
px("inch Hg 32F", get("inch").multiply(get("mercury 32F")));
px("inch Hg 60F", get("inch").multiply(get("mercury 60F")));
px("mm Hg 0C", get("m").scale(1e-3).multiply(get("mercury 0C")));
ps("cmHg", get("m").scale(1e-2).multiply(get("Hg")));
ps("cmH2O", get("m").scale(1e-2).multiply(get("water")));
px("inch Hg", get("inch").multiply(get("Hg")));
px("torr", get("m").scale(1e-3).multiply(get("Hg")));
px("foot H2O", get("foot").multiply(get("water")));
ps("psi", get("pound").multiply(
get("gravity").divide(get("inch").pow(2))));
ps("ksi", get("kip").divide(get("inch").pow(2)));
pn("barie", get("N").divide(get("m").pow(2)).scale(0.1));
px("footH2O", "foot H2O");
ps("ftH2O", "foot H2O");
pn("millimeter Hg", "torr");
px("mm Hg", "torr");
px("mm Hg", "torr");
pn("pascal", "Pa");
px("pal", "Pa");
ps("inHg", "inch Hg");
px("in Hg", "inch Hg");
ps("at", "technical atmosphere");
pn("atmosphere", "standard atmosphere");
ps("atm", "standard atmosphere");
pn("barye", "barie");
/*
* RADIATION UNITS
*/
ps("Ci", get("Bq").scale(3.7e10)); // exact
pn("rem", get("Sv").scale(1e-2)); // exact dose equivalent
ps("rd", get("Gy").scale(1e-2)); // absorbed dose. exact.
// use instead of "rad"
ps("R", get("C").divide(get("kg")).scale(2.58e-4));
ps("gray", "Gy");
px("sie", "Sv");
pn("becquerel", "Bq");
px("rads", "rd"); // avoid "rad" (radian)
pn("roentgen", "R");
pn("curie", "Ci");
/*
* VELOCITY (INCLUDES SPEED)
*/
ps("c", get("m").divide(get("s")).scale(2.997925e+8));
pn("kt", get("nautical mile").divide(get("h")));
px("knot international", "kt");
px("international knot", "kt");
pn("knot", "kt");
/*
* VISCOSITY
*/
ps("P", get("Pa").multiply(get("s")).scale(1e-1));
// exact
ps("St", get("m").pow(2).divide(get("s")).scale(1e-4));
// exact
ps("rhe", get("Pa").multiply(get("s")).pow(-1).scale(10));
pn("poise", "P");
pn("stokes", "St");
/*
* VOLUME (INCLUDES CAPACITY)
*/
px("acre feet", get("m").pow(3).scale(1.233489e3));
// but `acre foot' is 1233.4867714897 m^3. Odd.
px("board feet", get("m").pow(3).scale(2.359737e-3));
pn("bushel", get("m").pow(3).scale(3.523907e-2));
pn("UK liquid gallon", get("m").pow(3).scale(4.546090e-3)); // exact
pn("Canadian liquid gallon", get("m").pow(3).scale(4.546090e-3)); // exact
pn("US dry gallon", get("m").pow(3).scale(4.404884e-3));
pn("US liquid gallon", get("m").pow(3).scale(3.785412e-3));
ps("cc", get("m").scale(.01).pow(3));
pn("liter", get("m").pow(3).scale(1e-3));
// exact. However, from 1901 to 1964, 1 liter = 1.000028 dm3
pn("stere", get("m").pow(3)); // exact
ps("Bz", get("m").scale(1e-6).pow(3).log(10.0));
pn("register ton", get("m").pow(3).scale(2.831685));
pn("US dry quart", get("US dry gallon").scale(1. / 4));
pn("US dry pint", get("US dry gallon").scale(1. / 8));
pn("US liquid quart", get("US liquid gallon").scale(1. / 4));
pn("US liquid pint", get("US liquid gallon").scale(1. / 8));
pn("US liquid cup", get("US liquid gallon").scale(1. / 16));
pn("US liquid gill", get("US liquid gallon").scale(1. / 32));
pn("US liquid ounce", get("US liquid gallon").scale(1. / 128));
pn("UK liquid quart", get("UK liquid gallon").scale(1. / 4));
pn("UK liquid pint", get("UK liquid gallon").scale(1. / 8));
pn("UK liquid cup", get("UK liquid gallon").scale(1. / 16));
pn("UK liquid gill", get("UK liquid gallon").scale(1. / 32));
pn("UK liquid ounce", get("UK liquid gallon").scale(1. / 160));
pn("US fluid ounce", "US liquid ounce");
pn("UK fluid ounce", "UK liquid ounce");
pn("liquid gallon", "US liquid gallon");
pn("fluid ounce", "US fluid ounce");
pn("dry quart", "US dry quart");
pn("dry pint", "US dry pint");
pn("liquid quart", get("liquid gallon").scale(1. / 4));
pn("liquid pint", get("liquid gallon").scale(1. / 8));
ps("bbl", get("US liquid gallon").scale(42));
// petroleum industry definition
ps("pt", get("liquid pint"));
pn("gallon", "liquid gallon");
pn("quart", "liquid quart");
pn("cup", get("liquid gallon").scale(1. / 16));
pn("gill", get("liquid gallon").scale(1. / 32));
pn("tablespoon", get("US fluid ounce").scale(0.5));
pn("teaspoon", get("tablespoon").scale(1. / 3));
pn("peck", get("bushel").scale(1. / 4));
px("acre foot", "acre feet");
px("board foot", "board feet");
pn("barrel", "bbl");
ps("gal", get("gallon")); // "gal" is also
// (unused) acceleration unit
ps("oz", "fluid ounce");
px("floz", "fluid ounce");
pn("Tbl", "tablespoon");
ps("Tbsp", "tablespoon");
ps("tbsp", "tablespoon");
ps("Tblsp", "tablespoon");
ps("tblsp", "tablespoon");
pn("litre", "liter");
ps("L", "liter");
ps("l", "liter");
px("tsp", "teaspoon");
ps("pk", "peck");
ps("bu", "bushel");
ps("fldr", get("floz").scale(1. / 8));
ps("dr", get("floz").scale(1. / 16));
pn("firkin", get("bbl").scale(1. / 4));
// exact but "barrel" is vague
pn("pint", "pt");
ps("dram", "dr");
/*
* VOLUME PER UNIT TIME
*/
pn("sverdrup", get("m").pow(3).scale(1e6).divide(get("s"))); // oceanographic
// flow
/*
* COMPUTERS AND COMMUNICATION
*/
pn("bit", new ScaledUnit(1)); // unit of information
ps("Bd", get("Hz"));
ps("bps", get("Hz"));
ps("cps", get("cycle").divide(get("s")));
pn("baud", "Bd");
/*
* MISC
*/
pn("kayser", get("m").pow(-1).scale(1e2)); // exact
ps("rps", get("revolution").divide(get("s")));
ps("rpm", get("revolution").divide(get("min")));
px("geopotential", get("gravity"));
pn("work year", get("hours").scale(2056));
pn("work month", get("work year").scale(1. / 12));
pn("count", "");
ps("gp", "geopotential");
px("dynamic", "geopotential");
ps("gpm", get("geopotential").multiply(get("meter")));
// Potential vorticity unit:
ps("PVU", get("m").pow(2).divide(get("s")).multiply(get("K")).divide(get("kg")).scale(1e-6));
}
/**
* Gets an instance of this class.
*
* This is the only way to obtain an instance of this class.
*
* @throws UnitException
* Something went wrong in generating the singleton instance of
* the database. This should not occur and indicates an internal
* inconsistancy.
*/
public static UnitsDB instance() throws UnitException {
return db;
}
/**
* Get a unit.
*
* @param name
* The name of the unit to be retrieved. It may be the plural
* form (e.g. "yards"). If an entry in the database corresponding
* to the complete name is not found and the given name ends with
* an `s', then a search will be made for the singular form (e.g.
* "yard"). The matching entry will be returned only if the entry
* permits a plural form. The entry may also have one or more SI
* prefixes (e.g. "mega", "M").
* @return The appropriate unit or <code>null</code>. The unit will account
* for any SI prefixes in the name.
* @require The argument is non-<code>null</code>.
*/
@Override
public Unit get(final String name) {
Unit unit = super.get(name);
if (unit == null) {
// System.out.println("Entry \"" + name + "\" not found");
/*
* No entry by that name (including any possible plural form).
*/
/*
* Strip prefix.
*/
final Prefixer prefixer = new Prefixer(name);
if (prefixer.stripPrefix(prefixNames, prefixSymbols)) {
// System.out.println("Prefix found");
// System.out.println("Looking for \"" + prefixer.getString() +
// "\"");
/*
* Prefix found. Recurse on the rest of the string.
*/
if ((unit = get(prefixer.getString())) != null) {
try {
unit = unit.scale(prefixer.getValue());
}
catch (final UnitException e) {
unit = null;
}
}
}
}
return unit;
}
/**
* Adds a symbol to the database for a unit already in the database.
*/
protected void ps(final String symbol, final String unitID) {
putSymbol(symbol, super.get(unitID));
}
/**
* Adds a symbol and a new unit to the database.
*
* @throws UnitException
*/
protected void ps(final String symbol, final Unit unit)
throws UnitException {
putSymbol(symbol, unit.clone(symbol));
}
/**
* Adds a name, the plural form of the name, and a new unit to the database.
*
* @throws UnitException
*/
protected void pn(final String name, Unit unit) throws UnitException {
unit = unit.clone(name);
putName(name, unit);
putName(makePlural(name), unit);
}
/**
* Adds a name and it's regular plural form to the database for a unit
* that's already in the database.
*/
protected void pn(final String name, final String unitID) {
final Unit unit = super.get(unitID);
putName(name, unit);
putName(makePlural(name), unit);
}
/**
* Adds a name that has no plural form and a new unit to the database.
*
* @throws UnitException
*/
protected void px(final String name, final Unit unit) throws UnitException {
putName(name, unit.clone(name));
}
/**
* Adds a name that has no plural form to the database for a unit that's
* already in the database.
*/
protected void px(final String name, final String unitID) {
putName(name, super.get(unitID));
}
/**
* Inner (helper) class for parsing unit prefixes.
*/
protected class Prefixer {
/**
* The string being parsed.
*/
protected final String string;
/**
* The current position within the string.
*/
protected int pos;
/**
* The current value of the prefix.
*/
protected double value;
/**
* Construct.
*/
protected Prefixer(final String string) {
this.string = string;
this.pos = 0;
this.value = 1;
}
/**
* Strip leading prefix from the string.
*/
protected boolean stripPrefix(final UnitPrefix[] names,
final UnitPrefix[] symbols) {
/*
* Perform a case-insensitive search on the names.
*/
for (int icur = 0; icur < names.length; ++icur) {
final UnitPrefix prefix = names[icur];
if (string.regionMatches(true, pos, prefix.name, 0, prefix.name
.length())) {
value *= prefix.value;
pos += prefix.name.length();
return true;
}
}
/*
* Perform a case-sensitive search on the symbols.
*/
for (int icur = 0; icur < symbols.length; ++icur) {
final UnitPrefix prefix = symbols[icur];
if (string.startsWith(prefix.name, pos)) {
value *= prefix.value;
pos += prefix.name.length();
return true;
}
}
return false;
}
/**
* Indicate whether or not the beginning of the remainder of the string
* is less than a prefix.
*/
protected boolean isLessThan(final UnitPrefix prefix) {
int icomp = 1;
final int n = Math.min(prefix.name.length(), string.length() - pos);
for (int i = 0; i < n; ++i) {
icomp = Character.getNumericValue(string.charAt(pos + i))
- Character.getNumericValue(prefix.name.charAt(i));
if (icomp != 0) {
break;
}
}
// System.out.println(string.substring(pos) +
// (icomp < 0 ? " < " : " >= ") + prefix.name);
return icomp < 0;
}
/**
* Return the current, remaining string.
*/
protected String getString() {
return string.substring(pos);
}
/**
* Return the current prefix value.
*/
protected double getValue() {
return value;
}
}
/**
* Test this class.
*
* @exception java.lang.Exception
* A problem occurred.
*/
public static void main(final String[] args) throws Exception {
final UnitsDB db = DefaultUnitsDB.instance();
System.out.println("% = " + db.get("%"));
System.out.println("abampere = " + db.get("abampere"));
System.out.println("firkin = " + db.get("firkin"));
System.out.println("MiCrOmEgAfirkin = " + db.get("MiCrOmEgAfirkin"));
System.out.println("celsius = " + db.get("celsius"));
System.out.println("fahrenheit = " + db.get("fahrenheit"));
System.out.println("m = " + db.get("m"));
System.out.println("mm = " + db.get("mm"));
System.out.println("dam = " + db.get("dam"));
System.out.println("million = " + db.get("million"));
System.out.println("pascal = " + db.get("pascal"));
System.out.println("Tperm_0C = " + db.get("Tperm_0C"));
System.out.println("MILLIpoundal = " + db.get("MILLIpoundal"));
System.out.println("");
db.list();
}
}