UNIDATA LIBRARY FUNCTIONS UDUNITS(3)## NAME

udunits, utInit, utScan, utCalendar, utInvCalendar, utCon- vert, utPrint, utIsTime, utHasOrigin, utClear, utCopy, utScale, utDivide, utInvert, utMultiply, utRaise, utTerm - Unidata units library## SYNOPSIS

cc -Iunidata_inc... #include <udunits.h> int utInit( const char *path); int utIsInit(); int utScan( const char *spec, utUnit *unit); int utCalendar( double value; utUnit *unit, int *year, int *month, int *day, int *hour, int *minute, float *second); int utInvCalendar( int year, int month, int day, int hour, int minute, double second, utUnit *unit, double *value); int utConvert( const utUnit *from, const utUnit *to, double *slope, double *intercept); int *utPrint( const utUnit *unit, char **s); utUnit *utClear( utUnit *unit); Printed: 106.2.15 Last change: 2003-08-29 1 UNIDATA LIBRARY FUNCTIONS UDUNITS(3) int *utIsTime( const utUnit *unit); int *utHasOrigin( const utUnit *unit); utUnit *utCopy( const utUnit *source, utUnit *dest); utUnit *utScale( utUnit *source, double factor, utUnit *result); utUnit *utDivide( utUnit *numer, utUnit *denom, utUnit *result); utUnit *utInvert( utUnit *source, utUnit *result); utUnit *utMultiply( utUnit *term1, utUnit *term2, utUnit *result); utUnit *utRaise( utUnit *source, int power, utUnit *result); void utTerm();## DESCRIPTION

The Unidata units library, udunits, supports conversion of unit specifications between formatted and binary forms, arithmetic manipulation of unit specifications, and conver- sion of values between compatible scales of measurement. A unit is the amount by which a physical quantity is meas- ured. For example: Physical Quantity Possible Unit _________________ _____________ time weeks distance centimeters power watts A unit can have an origin associated with it -- in which Printed: 106.2.15 Last change: 2003-08-29 2 UNIDATA LIBRARY FUNCTIONS UDUNITS(3) case the unit and origin together define a scale. For exam- ple, the phrase "the temperature is 25 degrees Celsius" specifies a particular point on a measurement scale; whereas the phrase "the temperature difference is 25 degrees Cel- sius" specifies a unit with no origin and, hence, no associ- ated scale. If not remembered, this subtle distinction can cause problems when handling units. utInit() initializes the units package. Ifpathis non-NULL and not empty, then it specifies a units file containing initializing unit definitions; otherwise, the environment variable UDUNITS_PATH is checked and, if it exists and is not empty, then it is assumed to contain the pathname of the units file; otherwise, a compile-time default pathname is used. The definitions in the units file are read into memory. This function returns 0 on success, UT_ENOFILE if the units file doesn't exist, UT_ESYNTAX if the units file contains a syntax error, UT_EUNKNOWN if the units file contains an unknown specification, UT_EIO if an I/O error occurred while accessing the units file, and UT_EALLOC if a memory alloca- tion failure occurred. utIsInit() indicates whether or not the units package has been initialized. This function returns 0 if the package hasn't been initial- ized and !0 if the package has been initialized. utScan() converts the formatted unit specificationspecinto a binary unit structure and stores the result inunit. The binary representation is used for algebraic manipulation. This function returns 0 on success, UT_ENOINIT if the pack- age hasn't been initialized, UT_EINVALID if the unit argu- ment is a null pointer, UT_EUNKNOWN if the specification contains an unknown unit, and UT_ESYNTAX if the specifica- tion contains a syntax error. utCalendar() converts the amount,value, of the temporal unit,unit, into a UTC-referenced date and time (see, how- ever, the section on HANDLING TIME). The reference unit shall be a time unit and have an origin. This function returns 0 on success, UT_ENOINIT if the package hasn't been initialized and UT_EINVALID if the unit structure is not a temporal one. utInvCalendar() converts a UTC-referenced date and time into the amount,value, of the temporal unit,unit(see, however, the section on HANDLING TIME). The reference unit shall be a time unit and have an origin. This function returns 0 on success, UT_ENOINIT if the package hasn't been initialized Printed: 106.2.15 Last change: 2003-08-29 3 UNIDATA LIBRARY FUNCTIONS UDUNITS(3) and UT_EINVALID if the unit structure is not a temporal one. utConvert() returns the coefficients of the Galilean transformation (i.e. y = a*x + b) necessary to convert thefromunit into thetounit. The units must be compatible (i.e., their quotient must be dimensionless). On successful return,slopeandinterceptwill contain the values for the slope and intercept coefficients, respectively. This func- tion returns 0 on success, UT_ENOINIT if the package hasn't been initialized, UT_EINVALID if one of the unit structures is invalid, and UT_ECONVERT if the units are not converti- ble. utPrint() converts the binary unit structureunitinto a formatted unit specification and stores the string into a static buffer. The argumentsis set to point to the static buffer. The string should not be modified (it may, however, be copied) and will be overwritten by subsequent calls to this function. This function returns 0 on success, UT_ENOINIT if the package hasn't been initialized, and UT_EINVALID if the unit structure is invalid. On error, the string argument is set to NULL. utClear() clears a unit structure by setting it to the dimensionless value 1. utIsTime() returns true if the given unit structure refers to a time unit and false otherwise. This function ignores whether or not the unit has an origin. utHasOrigin() returns true of the given unit structure has an origin (i.e. defines a scale) and false otherwise. utCopy() copies the unit structuresourceto the unit struc- turedest. This function correctly handles the case where the same unit structure is referenced by the source and des- tination units. The address of the destination unit struc- ture is returned. utScale() scales the unit structuresourcebyfactor, stor- ing the result in the unit structureresult. This function correctly handles the case where the same unit structure is referenced by the source and result units. The address of the result unit structure is returned. utInvert() inverts the unit structuresource, storing the result in unit structureresult. Multiplying a unit by its reciprocal yields the dimensionless value 1. This function correctly handles the case where the source and result unit refer to the same structure. If successful, this function returns the address of the result unit structure; otherwise, it returns NULL. Printed: 106.2.15 Last change: 2003-08-29 4 UNIDATA LIBRARY FUNCTIONS UDUNITS(3) utDivide() divides unit structurenumerby unit structuredenomand stores the result in unit structureresult. This function correctly handles the case where the same unit structure is referenced by two or more arguments. If suc- cessful, this function returns the address of the result unit structure; otherwise, it returns NULL. utMultiply() multiplies unit structureterm1by unit struc- tureterm2and stores the result in unit structureresult. This function correctly handles the case where the same unit structure is referenced by two or more arguments. If suc- cessful, this function returns the address of the result unit structure; otherwise, it returns NULL. utRaise() raises the unit structuresourceby the powerpower, storing the result in the unit structureresult. This function correctly handles the case where the same unit structure is referenced by the source and result units. If successful, this function returns the address of the result unit structure; otherwise, it returns NULL. utTerm() terminates usage of this package. In particular, it frees all allocated memory. It should be called when the library is no longer needed.## HANDLING TIME

The udunits(3) package uses a mixed Gregorian/Julian calen- dar system. Dates prior to 1582-10-15 are assumed to use the Julian calendar, which was introduced by Julius Caesar in 46 BCE and is based on a year that is exactly 365.25 days long. Dates on and after 1582-10-15 are assumed to use the Gregorian calendar, which was introduced on that date and is based on a year that is exactly 365.2425 days long. (A year is actually approximately 365.242198781 days long.) Seem- ingly strange behavior of the udunits(3) package can result if a user-given time interval includes the changeover date. For example, utCalendar() and utInvCalendar() can be used to show that 1582-10-15 *preceeded* 1582-10-14 by 9 days.## EXAMPLES

Convert two data sets to a common unit, subtract one from the other, then save the result in a (different) output unit: if (utInit("") != 0) { /* handle initialization error */ } else { char *UnitString1, *UnitString2, *OutputUnitString; utUnit unit1, unit2, OutputUnit; ... if (utScan(UnitString1, &unit1) != 0 || utScan(UnitString2, &unit2) != 0 || Printed: 106.2.15 Last change: 2003-08-29 5 UNIDATA LIBRARY FUNCTIONS UDUNITS(3) utScan(OutputUnitString2, &OutputUnit) != 0) { /* * handle decode error */ } else { double InSlope, InIntercept; double OutSlope, OutIntercept; ... if (utConvert(&unit2, &unit1, &InSlope, &InIntercept) != 0 || utConvert(&unit1, &OutputUnit, &OutSlope, &OutIntercept) != 0) { /* * handle data-incompatibility */ } else { /* * process data using: * OutputValue = OutSlope*(Data1Value - * (InSlope*Data2Value + InIntercept)) * + OutIntercept */ } } utTerm(); } the above example could be made more efficient by testing the returned conversion factors for nearness to 1 and 0 and using appropriately streamlined processing expressions. Compute a threshold value corresponding to an input data value plus a user-specified delta (the units of the input data value and delta can differ): char *input_unit_string, *delta_unit_string; float input_value; utUnit input_unit, delta_unit; ... if (utScan(input_unit_string, &input_unit) != 0 || utScan(delta_unit_string, &delta_unit) != 0) { /* * handle decode error */ } else { double slope, intercept; ... if (utConvert(&delta_unit, &input_unit, &slope, &intercept) != 0) { /* * handle units incompatibility */ Printed: 106.2.15 Last change: 2003-08-29 6 UNIDATA LIBRARY FUNCTIONS UDUNITS(3) } else { float threshold = input_value + slope*delta_value + intercept; ... } } utTerm(); Compute the number of time intervals from a start time to a reference time: #include <stdio.h> #include <stdlib.h> #include "udunits.h" main() { if (utInit("/upc/cur/udunits/etc/udunits.dat") != 0) { (void) fputs("utInit() error0, stderr); } else { utUnit timecenters_unit; /* * NB: The following "time centers" specification gives both * the start time (January 1, 1990 at 00:00 UTC) and the * sampling interval (2 minutes). */ if (utScan("2 minutes since 1990-1-1", &timecenters_unit) != 0) { (void) fputs("utScan() error0, stderr); } else { /* * The following reference time is 1 hour later than * the above start time. */ int ref_year = 1990; int ref_month = 1; int ref_day = 1; int ref_hour = 1; int ref_minute = 0; float ref_second = 0;/* could be `double' double ref_value; (void) utInvCalendar(ref_year, ref_month, ref_day, ref_hour, ref_minute, ref_second, &timecenters_unit, &ref_value); /* * Exit successfully if the number of time intervals * between the start and reference times is correct. */ if (30 == ref_value) Printed: 106.2.15 Last change: 2003-08-29 7 UNIDATA LIBRARY FUNCTIONS UDUNITS(3) exit(0); } } abort(); }## FORMATTED UNIT SPECIFICATIONS

The following are examples of formatted unit specifications that can be interpreted by the utScan() function: 10 kilogram.meters/seconds2 10 kg-m/sec2 10 kg m/s^2 (PI radian)2 degF 100rpm geopotential meters 33 feet water A unit is specified as an arbitrary product of constants and unit names raised to arbitrary integral powers. Division is indicated by a slash `/'. Multiplication is indicated by whitespace, a period `.', or a hyphen `-'. Exponentiation is indicated by an integer suffix or by the exponentiation operators `^' and `**'. Parentheses may be used for group- ing and disambiguation. Arbitrary Galilean transformations (i.e. y = ax + b) are supported. In particular, temperature and time conversions are correctly handled. The specification: degF @ 32 indicates a Fahrenheit scale with the origin shifted to thirty-two degrees Fahrenheit (i.e. to zero degrees Cel- sius). The Celsius scale is equivalent to the following unit: 1.8 degR @ 273.15 Besides the character `@', the words `after', `from', `ref', and `since' may also be used. Note that multiplication takes precedence over origin-shift. In order of increasing precedence, the operations are origin-shift, division, mul- tiplication, and exponentiation. Units of time are similarly handled. The specification: seconds since 1992-10-8 15:15:42.5 -6:00 indicates seconds since October 8th, 1992 at 3 hours, 15 Printed: 106.2.15 Last change: 2003-08-29 8 UNIDATA LIBRARY FUNCTIONS UDUNITS(3) minutes and 42.5 seconds in the afternoon in the time zone which is six hours to the west of Coordinated Universal Time (i.e. Mountain Daylight Time). The time zone specification can also be written without a colon using one or two-digits (indicating hours) or three or four digits (indicating hours and minutes). utScan() understands most conventional prefixes and abbrevi- ations: Factor Prefix Abbreviation ______ __________ ____________ 1e24 yotta Y 1e21 zetta Z 1e18 exa E 1e15 peta P 1e12 tera T 1e9 giga G 1e6 mega M 1e3 kilo k 1e2 hecto h 1e1 deca, deka da 1e-1 deci d 1e-2 centi c 1e-3 milli m 1e-6 micro u 1e-9 nano n 1e-12 pico p 1e-15 femto f 1e-18 atto a 1e-21 zepto z 1e-24 yocto y The function utPrint() always encodes a unit specification one way. To reduce misunderstandings, it is recommended that this encoding style be used as the default. In general, a unit is printed in terms of basic units, factors, and exponents. Basic units are separated by spaces; and any exponent directly appends its associated unit. The above examples would be printed as follows: 10 kilogram meter second-2 9.8696044 radian2 0.555556 kelvin @ 255.372 10.471976 radian second-1 9.80665 meter2 second-2 98636.5 kilogram meter-1 second-2 Note that the Fahrenheit unit is encoded as a deviation, in fractional kelvins, from an origin at 255.372 kelvin. Printed: 106.2.15 Last change: 2003-08-29 9 UNIDATA LIBRARY FUNCTIONS UDUNITS(3)## UNITS FILE

The units file is a formatted file containing unit defini- tions and is used to initialize this package. It is the first place to look to discover the set of valid names and symbols (of which there are many -- On October 9, 1992, it contained 446 entries). The format for the units file is documented internally and the file may be modified by the user as necessary. In par- ticular, additional units and constants may be easily added (including variant spellings of existing units or con- stants).## ENVIRONMENT

UDUNITS_PATH If utInit() is called without a pathname argument, and if this environment variable is non-empty, then its value overrides the default pathname for the units file.## DIAGNOSTICS

This package prints (hopefully) self-explanatory error- messages to standard error.## SEE ALSO

udunits(1).## BUGS AND RESTRICTIONS

utScan() is case-sensitive. If this causes difficulties, you might try making appropriate additional entries to the units file. Some unit abbreviations in the default units file might seem counter-intuitive. In particular, note the following: For Use Not Which Instead Means Celsius `Celsius' `C' coulomb gram `gram' `g' <standard free fall> gallon `gallon' `gal' <acceleration> radian `radian' `rad' <absorbed dose> Newton `newton' or `N' `nt' nit (unit of photometry)## REFERENCES

NIST Special Publication 811, 1995 Edition: "Guide for the Use of the International System of Units (SI)" by Barry N. Taylor. URL <http://physics.nist.gov/Divisions/Div840/SI.html>. ANSI/IEEE Std 260-1978: "IEEE Standard Letter Symbols for Units of Measurement". Printed: 106.2.15 Last change: 2003-08-29 10 UNIDATA LIBRARY FUNCTIONS UDUNITS(3) ASTM Designation: E 380 - 85: "Standard for METRIC PRAC- TICE". International Standard (ISO) 2955: "Information processing -- Representation of SI and other units in systems with lim- ited character sets", Ref. No. ISO 2955-1983 (E). Printed: 106.2.15 Last change: 2003-08-29 11

© 1994 Man-cgi 1.14, Panagiotis Christias <christia@theseas.ntua.gr>