utScale, utDivide, utInvert, utMultiply, utRaise, utTerm -
Unidata units library
SYNOPSIS
cc -Iunidata_inc ...
#include <udunits.h>
int utInit(
const char *path);
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);
int *utIsTime(
const utUnit *unit);
int *utHasOrigin(
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 con
version of values between compatible scales of measure
ment.
A unit is the amount by which a physical quantity is mea
sured. For example:
A unit can have an origin associated with it -- in which
case the unit and origin together define a scale. For
example, the phrase "the temperature is 25 degrees Cel
sius" specifies a particular point on a measurement scale;
whereas the phrase "the temperature difference is 25
degrees Celsius" specifies a unit with no origin and,
hence, no associated scale. If not remembered, this sub
tle distinction can cause problems when handling units.
utInit() initializes the units package. If path is non-
NULL and not empty, then it specifies a units file con
taining 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
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 func
tion returns 0 on success, UT_ENOINIT if the package
hasn't been initialized and UT_EINVALID if the unit struc
ture is not a temporal one.
utConvert() returns the coefficients of the Galilean
transformation (i.e. y = a*x + b) necessary to convert the
from unit into the to unit. The units must be compatible
(i.e., their quotient must be dimensionless). On success
ful return, slope and intercept will contain the values
for the slope and intercept coefficients, respectively.
This function 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 convertible.
utPrint() converts the binary unit structure unit into a
formatted unit specification and stores the string into a
static buffer. The argument s is 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 suc
cess, 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 structure source to the unit
structure dest. This function correctly handles the case
where the same unit structure is referenced by the source
and destination units. The address of the destination
unit structure is returned.
utScale() scales the unit structure source by factor,
denom and stores the result in unit structure result.
This function correctly handles the case where the same
unit structure is referenced by two or more arguments. If
successful, this function returns the address of the
result unit structure; otherwise, it returns NULL.
utMultiply() multiplies unit structure term1 by unit
structure term2 and stores the result in unit structure
result. This function correctly handles the case where
the same unit structure is referenced by two or more argu
ments. If successful, this function returns the address
of the result unit structure; otherwise, it returns NULL.
utRaise() raises the unit structure source by the power
power, storing the result in the unit structure result.
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 cal
endar 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 intro
duced 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.) Seemingly 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 ||
*/
} 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 expres
sions.
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
*/
} 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>
*/
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)
exit(0);
}
}
abort();
}
FORMATTED UNIT SPECIFICATIONS
The following are examples of formatted unit specifica
tions 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. Divi
sion is indicated by a slash `/'. Multiplication is indi
cated by whitespace, a period `.', or a hyphen `-'. Expo
nentiation is indicated by an integer suffix or by the
exponentiation operators `^' and `**'. Parentheses may be
used for grouping and disambiguation.
Besides the character `@', the words `after', `from',
`ref', and `since' may also be used. Note that the ori
gin-shift operation takes precedence over multiplication.
In order of increasing precedence, the operations are
division, multiplication, origin-shift, and exponentia
tion.
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
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 speci
fication 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 abbre
viations:
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 gen
eral, 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.
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
particular, additional units and constants may be easily
added (including variant spellings of existing units or
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 follow
ing:
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/Divi
sions/Div840/SI.html>.
ANSI/IEEE Std 260-1978: "IEEE Standard Letter Symbols for
Units of Measurement".
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
limited character sets", Ref. No. ISO 2955-1983 (E).
Printed: 105.10.10 1996-12-02 UDUNITS(3)
Man(1) output converted with
man2html