/* * Copyright (c) 2003-2010 Hypertriton, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 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. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Unit conversions (taken from Agar-1.3.4). */ #include #include #include #include #define N_(x) (x) #define _(x) (x) const char *agUnitGroupNames[] = { N_("Identity"), N_("Length"), N_("Angle"), N_("Area"), N_("Volume"), N_("Velocity"), N_("Mass"), N_("Time"), N_("Electrical current"), N_("Temperature"), N_("Light"), N_("Power"), N_("Electromotive force"), N_("Electrical resistance"), N_("Capacitance"), N_("Inductance"), N_("Frequency"), N_("Pressure"), N_("Vacuum"), NULL }; const cnc_unit_t *cnc_unit_groups[] = { cncIdentityUnit, cncLengthUnits, cncAngleUnits, cncAreaUnits, cncVolumeUnits, cncSpeedUnits, cncMassUnits, cncTimeUnits, cncCurrentUnits, cncTemperatureUnits, cncLightUnits, cncPowerUnits, cncEMFUnits, cncResistanceUnits, cncCapacitanceUnits, cncInductanceUnits, cncFrequencyUnits, cncPressureUnits, cncVacuumUnits, }; const int cnc_unit_groups_count = sizeof(cnc_unit_groups) / sizeof(cnc_unit_groups[0]); /* * Return the unit of specified key, searching in all groups. * If key=NULL, return the base unit. */ const cnc_unit_t * cnc_find_unit_all(const char *key) { int i; for (i = 0; i < cnc_unit_groups_count; i++) { const cnc_unit_t *group = cnc_unit_groups[i]; const cnc_unit_t *unit; for (unit = &group[0]; unit->key != NULL; unit++) { if (key == NULL) { if (unit->divider == 1) return (unit); } else { if (strcmp(unit->key, key) == 0) return (unit); } } } cnc_set_error("No such unit: %s", key); return (NULL); } /* * Return the unit of specified key, searching in all groups. * If key=NULL, return the base unit. */ const cnc_unit_t * cnc_find_unit(const char *key, const cnc_unit_t *group) { const cnc_unit_t *unit; for (unit = &group[0]; unit->key != NULL; unit++) { if (key == NULL) { if (unit->divider == 1) return (unit); } else { if (strcmp(unit->key, key) == 0) return (unit); } } cnc_set_error("No such unit: %s", key); return (NULL); } /* Return the unit which yields the number with the least figures. */ const cnc_unit_t * cnc_best_unit(const cnc_unit_t ugroup[], double n) { const cnc_unit_t *unit, *bestunit = NULL; double smallest = HUGE_VAL; double diff; if (n == 0) { goto defunit; } for (unit = &ugroup[0]; unit->key != NULL; unit++) { if (n/unit->divider >= 1.0) { diff = fabs(n-unit->divider); if (diff < smallest) { smallest = diff; bestunit = unit; } } } if (bestunit == NULL) { goto defunit; } return (bestunit); defunit: for (unit = &ugroup[0]; unit->key != NULL; unit++) { if (unit->divider == 1.0) break; } return (unit); } /* Format a number using the unit most suited to its magnitude. */ int cnc_unit_format(double n, const cnc_unit_t ugroup[], char *buf, size_t len) { const cnc_unit_t *ubest; ubest = cnc_best_unit(ugroup, n); return (snprintf(buf, len, "%.2f%s", cnc_base2unit(n, ubest), ubest->abbr[0] != '\0' ? ubest->abbr : ubest->key)); } /* Default unit (identity) */ const cnc_unit_t cncIdentityUnit[] = { { "identity", "", "", 1.0, NULL }, { NULL, NULL, NULL, 0, NULL } }; /* Units of length/distance */ const cnc_unit_t cncLengthUnits[] = { { "Ang", "\xc3\x85", N_("\xc3\x85ngstroms"), 1e-10, NULL }, { "fm", "", N_("Femtometres"), 1e-15, NULL }, { "pm", "", N_("Picometres"), 1e-12, NULL }, { "nm", "", N_("Nanometres"), 1e-9, NULL }, { "um", "\xc2\xb5", N_("Microns"), 1e-6, NULL }, { "mil", "", N_("Mils"), 25e-6, NULL }, { "mm", "", N_("Millimeters"), 1e-3, NULL }, { "in", "", N_("Inches"), 0.0254, NULL }, { "cm", "", N_("Centimeters"), 1e-2, NULL }, { "dm", "", N_("Decimeters"), 0.1, NULL }, { "ft", "", N_("Feet"), 0.3048, NULL }, { "yd", "", N_("Yards"), 0.9144, NULL }, { "m", "", N_("Meters"), 1.0, NULL }, { "km", "", N_("Kilometers"), 1000, NULL }, { "mi", "", N_("Miles"), 1609.344, NULL }, { NULL, NULL, NULL, 0, NULL } }; /* Units of angle */ const cnc_unit_t cncAngleUnits[] = { { "rad", "", N_("Radians"), 1.0, NULL }, { "deg", "\xc2\xb0", N_("Degrees"), 0.01745329251994329577, NULL }, { "rev", "", N_("Revolutions"), 6.28318530717958647692, NULL }, { "grad", "", N_("Grads"), 0.01570796326794896619, NULL }, { "point", "", N_("Points"), 0.19634954084936207740, NULL }, { "brad", "", N_("Binary degrees"), 0.02454369260617025968, NULL }, { "HA", "", N_("Hour angle"), 0.26179938779914943654, NULL }, { NULL, NULL, NULL, 0, NULL } }; /* Units of area (SI derived) */ const cnc_unit_t cncAreaUnits[] = { { "um^2", "\xc2\xb5\xc2\xb2", N_("Square micrometers"), 1e-6, NULL }, { "mm^2", "mm\xc2\xb2", N_("Square millimeters"), 1e-3, NULL }, { "cm^2", "cm\xc2\xb2", N_("Square centimeters"), 1e-2, NULL }, { "in^2", "in\xc2\xb2", N_("Square inches"), 0.0254, NULL }, { "ft^2", "ft\xc2\xb2", N_("Square feet"), 0.3048, NULL }, { "yd^2", "yd\xc2\xb2", N_("Square yards"), 0.9144, NULL }, { "m^2", "m\xc2\xb2", N_("Square meters"), 1.0, NULL }, { "km^2", "km\xc2\xb2", N_("Square kilometers"), 1000, NULL }, { "mi^2", "mi\xc2\xb2", N_("Square miles"), 1609.35, NULL }, { NULL, NULL, NULL, 0, NULL } }; /* Units of volume (SI derived) */ const cnc_unit_t cncVolumeUnits[] = { { "um^3", "\xc2\xb5m\xc2\xb3", N_("Cubic micrometers"), 1e-6, NULL }, { "mm^3", "mm\xc2\xb3", N_("Cubic millimeters"), 1e-3, NULL }, { "cm^3", "cm\xc2\xb3", N_("Cubic centimeters"), 1e-2, NULL }, { "in^3", "in\xc2\xb3", N_("Cubic inches"), 0.0254, NULL }, { "ft^3", "ft\xc2\xb3", N_("Cubic feet"), 0.3048, NULL }, { "yd^3", "yd\xc2\xb3", N_("Cubic yards"), 0.9144, NULL }, { "m^3", "m\xc2\xb3", N_("Cubic meters"), 1.0, NULL }, { "km^3", "km\xc2\xb3", N_("Cubic kilometers"), 1e3, NULL }, { "mi^3", "mi\xc2\xb3", N_("Cubic miles"), 1609.35, NULL }, { NULL, NULL, NULL, 0, NULL } }; /* Units of speed/velocity (SI derived) */ const cnc_unit_t cncSpeedUnits[] = { { "um/s", "\xc2\xb5m/s", N_("Micrometers per second"), 1e-6, NULL }, { "mm/s", "", N_("Millimeters per second"), 1e-3, NULL }, { "cm/s", "", N_("Centimeters per second"), 1e-2, NULL }, { "in/s", "", N_("Inches per second"), 0.0254, NULL }, { "ft/s", "", N_("Feet per second"), 0.3048, NULL }, { "yd/s", "", N_("Yards per second"), 0.9144, NULL }, { "m/s", "", N_("Meters per second"), 1.0, NULL }, { "km/s", "", N_("Kilometers per second"), 1e3, NULL }, { "mi/s", "", N_("Miles per second"), 1609.35, NULL }, { NULL, NULL, NULL, 0, NULL } }; /* Units of weight */ const cnc_unit_t cncMassUnits[] = { { "ug", "\xc2\xb5g", N_("Micrograms"), 1e-6, NULL }, { "mg", "", N_("Milligrams"), 1e-3, NULL }, { "cg", "", N_("Centigrams"), 1e-2, NULL }, { "dg", "", N_("Decigrams"), 1e-1, NULL }, { "g", "", N_("Grams"), 1.0, NULL }, { "oz", "", N_("Ounces [comm]"), 28.349, NULL }, { "lb", "", N_("Pounds [comm]"), 453.59, NULL }, { "kg", "", N_("Kilograms"), 1e3, NULL }, { "t(s)", "", N_("Tons [short]"), 907200, NULL }, { "t", "", N_("Tons [metric]"), 1e6, NULL }, { "t(l)", "", N_("Tons [long]"), 1016064, NULL }, { NULL, NULL, NULL, 0, NULL } }; /* Units of time */ const cnc_unit_t cncTimeUnits[] = { { "ns", "", N_("Nanoseconds"), 1e-9, NULL }, { "us", "\xc2\xb5s", N_("Microseconds"), 1e-6, NULL }, { "ms", "", N_("Milliseconds"), 1e-3, NULL }, { "sec", "", N_("Seconds"), 1.0, NULL }, { "min", "", N_("Minutes"), 60, NULL }, { "hr", "", N_("Hours"), 3600, NULL }, { "day", "", N_("Days"), 86400, NULL }, { "wk", "", N_("Weeks"), 604800, NULL }, { "yr", "", N_("Years"), 31104000, NULL }, { NULL, NULL, NULL, 0, NULL } }; /* Units of electrical current */ const cnc_unit_t cncCurrentUnits[] = { { "pA", "", N_("Picoamperes"), 1e-12, NULL }, { "nA", "", N_("Nanoamperes"), 1e-9, NULL }, { "uA", "\xc2\xb5\x41", N_("Microamperes"), 1e-6, NULL }, { "mA", "", N_("Milliamperes"), 1e-3, NULL }, { "A", "", N_("Amperes"), 1.0, NULL }, { "kA", "", N_("Kiloamperes"), 1e3, NULL }, { "MA", "", N_("Megaamperes"), 1e6, NULL }, { NULL, NULL, NULL, 0, NULL } }; static double cnc_conv_Fahrenheit(double n, int f2k) { if (f2k) { return ((n+459.67) / 1.8); } else { return (1.8*n - 459.67); } } static double cnc_conv_Celsius(double n, int c2k) { if (c2k) { return (n+273.15); } else { return (n-273.15); } } const cnc_unit_t cncTemperatureUnits[] = { { "degC", "\xc2\xb0\x43", N_("Degrees Celsius"), 0, cnc_conv_Celsius }, { "degF", "\xc2\xb0\x46", N_("Degrees Farenheit"), 0, cnc_conv_Fahrenheit}, { "uk", "\xc2\xb5k", "Microkelvins", 1e-6, NULL }, { "mk", "", "Millikelvins", 1e-3, NULL }, { "k", "", "Kelvins", 1.0, NULL }, { "kk", "", "Kilokelvins", 1e3, NULL }, { "Mk", "", N_("Megakelvins"), 1e6, NULL }, { NULL, NULL, NULL, 0, NULL } }; /* Units of light measurement */ const cnc_unit_t cncLightUnits[] = { { "ucd", "\xc2\xb5\x63\x64", "Microcandelas", 1e-6, NULL }, { "mcd", "", "Millicandelas", 1e-3, NULL }, { "cd", "", "Candelas", 1.0, NULL }, { "kcd", "", "Kilocandelas", 1e3, NULL }, { "Mcd", "", N_("Megacandelas"), 1e6, NULL }, { NULL, NULL, NULL, 0, NULL } }; /* Units of power */ const cnc_unit_t cncPowerUnits[] = { { "uW", "\xc2\xb5W", "Microwatts", 1e-6, NULL }, { "mW", "", "Milliwatts", 1e-3, NULL }, { "BTU/h", "", "BTU/hr", 0.292875, NULL }, { "f-lb/s", "", N_("Foot-lbs/sec"), 1.355818, NULL }, { "W", "", "Watts", 1.0, NULL }, { "kC/m", "", "Kilocalories/min", 69.733, NULL }, { "HP", "", N_("Horsepower"), 746, NULL }, { "kW", "", "Kilowatts", 1e3, NULL }, { "kC/s", "", "Kilocalories/sec", 4183.98, NULL }, { "MW", "", N_("Megawatts"), 1e6, NULL }, { "GW", "", "Gigawatts", 1e9, NULL }, { NULL, NULL, NULL, 0, NULL } }; /* Units of electromotive force */ const cnc_unit_t cncEMFUnits[] = { { "uV", "\xc2\xb5V", "Microvolts", 1e-6, NULL }, { "mV", "", "Millivolts", 1e-3, NULL }, { "V", "", "Volts", 1.0, NULL }, { "kV", "", "Kilovolts", 1e3, NULL }, { "MV", "", N_("Megavolts"), 1e6, NULL }, { NULL, NULL, NULL, 0, NULL } }; /* Units of electrical resistance */ const cnc_unit_t cncResistanceUnits[] = { { "uohm", "\xc2\xb5\xce\xa9", "Microohms", 1e-6, NULL }, { "mohm", "m\xce\xa9", "Milliohms", 1e-3, NULL }, { "ohm", "\xce\xa9", "Ohms", 1.0, NULL }, { "kohm", "k\xce\xa9", "Kilohms", 1e3, NULL }, { "Mohm", "M\xce\xa9", N_("Megaohms"), 1e6, NULL }, { NULL, NULL, NULL, 0, NULL } }; /* Units of electrical capacitance */ const cnc_unit_t cncCapacitanceUnits[] = { { "pF", "", "Picofarads", 1e-12, NULL }, { "nF", "", "Nanofarads", 1e-9, NULL }, { "uF", "\xc2\xb5\x46", "Microfarads", 1e-6, NULL }, { "mF", "", "Millifarads", 1e-3, NULL }, { "F", "", "Farads", 1.0, NULL }, { "kF", "", "Kilofarads", 1e3, NULL }, { NULL, NULL, NULL, 0, NULL } }; /* Units of electrical inductance */ const cnc_unit_t cncInductanceUnits[] = { { "uH", "\xc2\xb5\x48", "Microhenries", 1e-6, NULL }, { "mH", "", "Millihenries", 1e-3, NULL }, { "H", "", "Henries", 1.0, NULL }, { "kH", "", "Kilohenries", 1e3, NULL }, { NULL, NULL, NULL, 0, NULL } }; /* Units of frequency */ const cnc_unit_t cncFrequencyUnits[] = { { "uHz", "\xc2\xb5Hz","Microhertz", 1e-6, NULL }, { "mHz", "", "Millihertz", 1e-3, NULL }, { "Hz", "", "Hertz", 1.0, NULL }, { "kHz", "", "Kilohertz", 1e3, NULL }, { "MHz", "", N_("Megahertz"), 1e6, NULL }, { "GHz", "", "Gigahertz", 1e9, NULL }, { NULL, NULL, NULL, 0, NULL } }; /* Units of pressure and stress */ const cnc_unit_t cncPressureUnits[] = { { "Pa", "", "Pascals", 1.0, NULL }, { "mbar", "", "Millibars", 1e2, NULL }, { "kPa", "", "Kilopascals", 1e3, NULL }, { "bar", "", "Bars", 1e5, NULL }, { "Kg-f/m^2", "Kg-f/m\xc2\xb2", N_("Kg-force per m\xc2\xb2"), 9.80665, NULL }, { "cm H2O", "cm H\xc2\xb2O", N_("Centimeters of water"), 98.0665, NULL }, { "in H2O", "in H\xc2\xb2O", N_("Inches of water"), 249.08891, NULL }, { "cm Hg", "", N_("Centimeters of mercury"), 1333.22, NULL }, { "Ft H2O", "Ft H\xc2\xb2O", N_("Feet of water"), 2989.06692, NULL }, { "in Hg", "", N_("Inches of mercury"), 3386.388, NULL }, { "m H2O", "m H\xc2\xb2O", N_("Meters of water"), 9806.65, NULL }, { "Kips/in^2", "Kips/in\xc2\xb2", N_("Kips per in\xc2\xb2"), 6894760, NULL }, { "Atm", "", N_("Atmospheres"), 101325, NULL }, { NULL, NULL, NULL, 0, NULL } }; /* Units of vacuum pressure */ const cnc_unit_t cncVacuumUnits[] = { { "ubar(V)", "\xc2\xb5\x62\x61\x72", N_("Microbar"), 0.000750062, NULL }, { "Pa(V)", "Pa", N_("Pascals"), 0.007500617, NULL }, { "N/m^2(V)", "N/m\xc2\xb2", N_("Newtons per m\xc2\xb2"), 0.007500617, NULL }, { "mtorr(V)", "mtorr", N_("Millitorr"), 0.001, NULL }, { "micron Hg(V)", "micron Hg", N_("Microns of Mercury"), 0.001, NULL }, { "mbar(V)", "mbar", N_("Millibar"), 0.75030012004802, NULL }, { "torr(V)", "torr", N_("Torr"), 1.0, NULL }, { "mm Hg(V)", "mm Hg", N_("Millimeters of Mercury"), 1.0, NULL }, { "in H2O(V-4C)", "in H\xc2\xb2O (4\xc2\xb0\x43)", N_("Inches of Water (4\xc2\xb0\x43)"), 1.868268641, NULL }, { "in H2O(V-60F)", "in H\xc2\xb2O (60\xc2\xb0\x46)", N_("Inches of Water (60\xc2\xb0\x46)"), 1.866475993, NULL }, { "in Hg(V-32F)", "in Hg (32\xc2\xb0\x46)", N_("Inches of Mercury (32\xc2\xb0\x46)"), 25.399938811, NULL }, { "in Hg(V-60F)", "in Hg (60\xc2\xb0\x46)", N_("Inches of Mercury (60\xc2\xb0\x46)"), 25.328457932, NULL }, { "psi(V)", "psi", N_("Pounds per in\xc2\xb2"), 51.714932572, NULL }, { "at(V)", "at", N_("Atmospheres technical"), 735.559240069, NULL }, { "kg/cm^2(V)", "kg/cm\xc2\xb2", N_("Kilograms per cm\xc2\xb2"),735.56454579, NULL }, { "bar(V)", "bar", N_("Bar"), 750.30012004, NULL }, { "dynes/cm^2(V)", "dynes/cm\xc2\xb2", N_("Dynes per cm\xc2\xb2"), 750.33012004, NULL }, { "Atm(V)", "Atm", N_("Standard atmospheres"), 760.0, NULL }, { NULL, NULL, NULL, 0.0, NULL } };