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);
int *utIsTime(
const utUnit *unit);
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 conversion of values between
compatible scales of measurement.
A unit is the amount by which a physical quantity is measured. For
example:
\!.3rmk "\$1"
\!.nr 3crow 0
\!.3rvpt "\$1"
??Physical Quantity?? ??Possible Unit??
\!.3rvpt "\$1"
\!.nr 3brule 1
\!.3rvpt "\$1"
\!.nr 3crow 1
\!.3rmk "\$1"
\!.3rvpt "\$1"
\!.3rvpt "\$1"
\!.nr 3brule 1
\!.3rvpt "\$1"
\!.3rvpt "\$1"
??distance?? ??centimeters??
\!.3rvpt "\$1"
\!.nr 3brule 1
\!.3rvpt "\$1"
\!.3rmk "\$1"
\!.nr 3crow 4
\!.3rvpt "\$1"
??power?? ??watts??
\!.3rvpt "\$1"
\!.nr 3brule 1
\!.3rvpt "\$1"
\!.3rvpt "\$1"
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 Celsius" 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 subtle 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 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 allocation failure occurred.
utIsInit()
UT_ESYNTAX if the specification contains a syntax error.
utCalendar()
converts the amount, value, of the temporal unit, unit,
into a UTC-referenced date and time
(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 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 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 the from unit into the to unit.
The units must be compatible (i.e., their quotient must be dimensionless).
On successful 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 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.
factor, 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.
The address of the result unit structure is returned.
utInvert()
inverts the unit structure source, storing the result in
unit structure result.
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.
utDivide()
divides unit structure numer by unit structure 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 arguments.
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 calendar 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.) Seemingly strange
behavior of the udunits(3) package can result if a user-given time
if (utScan(UnitString1, &unit1) != 0 ||
utScan(UnitString2, &unit2) != 0 ||
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) {
/*
#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)
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
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 Celsius). 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, multiplication, 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 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 abbreviations:
\!.3rmk "\$1"
\!.nr 3crow 0
\!.3rvpt "\$1"
??Factor?? ??Prefix?? ??Abbreviation??
\!.3rvpt "\$1"
\!.nr 3brule 1
\!.3rvpt "\$1"
\!.nr 3crow 1
\!.3rmk "\$1"
\!.3rvpt "\$1"
\!.3rvpt "\$1"
\!.nr 3brule 1
\!.3rmk "\$1"
\!.nr 3crow 3
\!.3rvpt "\$1"
1e21 zetta ??Z??
\!.3rvpt "\$1"
\!.nr 3brule 1
\!.3rvpt "\$1"
\!.3rmk "\$1"
\!.nr 3crow 4
\!.3rvpt "\$1"
1e18 exa ??E??
\!.3rvpt "\$1"
\!.nr 3brule 1
\!.3rvpt "\$1"
\!.3rmk "\$1"
\!.nr 3crow 5
\!.3rvpt "\$1"
1e15 peta ??P??
\!.3rvpt "\$1"
\!.nr 3brule 1
\!.3rvpt "\$1"
\!.3rmk "\$1"
\!.nr 3crow 6
\!.3rvpt "\$1"
1e12 tera ??T??
\!.3rvpt "\$1"
\!.nr 3brule 1
\!.3rvpt "\$1"
\!.3rmk "\$1"
\!.nr 3crow 7
\!.3rvpt "\$1"
\!.3rvpt "\$1"
\!.nr 3brule 1
\!.3rvpt "\$1"
\!.3rmk "\$1"
\!.nr 3crow 9
\!.3rvpt "\$1"
1e3 kilo ??k??
\!.3rvpt "\$1"
\!.nr 3brule 1
\!.3rvpt "\$1"
\!.3rmk "\$1"
\!.nr 3crow 10
\!.3rvpt "\$1"
1e2 hecto ??h??
\!.3rvpt "\$1"
\!.nr 3brule 1
\!.3rvpt "\$1"
\!.3rmk "\$1"
\!.nr 3crow 11
\!.3rvpt "\$1"
1e1 deca, deka ??da??
\!.3rvpt "\$1"
\!.nr 3brule 1
\!.3rvpt "\$1"
\!.3rmk "\$1"
\!.nr 3crow 12
\!.3rvpt "\$1"
1e-1 deci ??d??
\!.3rvpt "\$1"
\!.nr 3brule 1
\!.3rmk "\$1"
\!.nr 3crow 14
\!.3rvpt "\$1"
1e-3 milli ??m??
\!.3rvpt "\$1"
\!.nr 3brule 1
\!.3rvpt "\$1"
\!.3rmk "\$1"
\!.nr 3crow 15
\!.3rvpt "\$1"
1e-6 micro ??u??
\!.3rvpt "\$1"
\!.nr 3brule 1
\!.3rvpt "\$1"
\!.3rmk "\$1"
\!.nr 3crow 16
\!.3rvpt "\$1"
1e-9 nano ??n??
\!.3rvpt "\$1"
\!.nr 3brule 1
\!.3rvpt "\$1"
\!.3rmk "\$1"
\!.nr 3crow 17
\!.3rvpt "\$1"
1e-12 pico ??p??
\!.3rvpt "\$1"
\!.nr 3brule 1
\!.3rvpt "\$1"
\!.3rmk "\$1"
\!.nr 3crow 18
\!.3rvpt "\$1"
\!.3rvpt "\$1"
\!.nr 3brule 1
\!.3rvpt "\$1"
\!.3rmk "\$1"
\!.nr 3crow 20
\!.3rvpt "\$1"
1e-21 zepto ??z??
\!.3rvpt "\$1"
\!.nr 3brule 1
\!.3rvpt "\$1"
\!.3rmk "\$1"
\!.nr 3crow 21
\!.3rvpt "\$1"
1e-24 yocto ??y??
\!.3rvpt "\$1"
\!.nr 3brule 1
\!.3rvpt "\$1"
\!.3rvpt "\$1"
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
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".
ASTM Designation: E 380 - 85: "Standard for METRIC PRACTICE".
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: 0.0.0 $Date: 2003/08/29 18:29:55 $ UDUNITS(3)
Man(1) output converted with
man2html