UDUNITS(3f)

NAME
udunits, utopen, utmake, uttime, utorigin, utclr, utcpy, utorig, utscal, utmult, utinv, utdiv, utexp, utdec, utcaltime, uticaltime, utenc, utcvt, utfree, utcls - Unidata units library

SYNOPSIS
f77 -Iunidata_inc -Lunidata_lib -ludunits ...

include udunits.inc

integer function	utopen	(character*(*) path)

PTR function	utmake	()

integer function	uttime	(PTR unit)

integer function	utorigin	(PTR unit)

subroutine	utclr	(PTR unit)

subroutine	utcpy	(PTR source, PTR dest)

subroutine	utorig	(PTR source,
			doubleprecision amount,
			PTR result)

subroutine	utscal	(PTR source,
			doubleprecision factor,
			PTR result)

subroutine	utmult	(PTR term1, PTR term2,
			PTR result)

subroutine	utinv	(PTR source, PTR result)

subroutine	utdiv	(PTR numer, PTR denom,
			PTR result)

subroutine	utexp	(PTR source, integer power,
			PTR result)

integer function	utdec	(character*(*) spec, PTR unit)

integer function	utcaltime	(doubleprecision value,
			PTR unit,
			integer year,
			integer month,
			integer day,
			integer hour,
			integer minute,
			real second)

integer function	uticaltime	(integer year,
			integer month,
			integer day,
			integer hour,
			integer minute,
			real second
			PTR unit,
			doubleprecision value)

integer function	utenc	(PTR unit, character*(*) spec)

integer function	utcvt	(PTR from, PTR to,
			doubleprecision slope,
			doubleprecision intercept)

subroutine	utfree	(PTR unit)

subroutine	utcls	()

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:

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.

Because the units library passes pointers to units structures and FORTRAN 77 has no pointer type, the word PTR in the above synopsis stands for whatever FORTRAN type is appropriate for holding a pointer to a C structure on the given platform. This is necessarily platform-dependent and, consequently, IT IS UP TO THE USER TO DECLARE AND USE THE CORRECT FORTRAN DATA TYPE.

utopen() initializes the units package. If path is not empty, then it specifies a units file containing initializing unit definitions; otherwise, the environment variable UDUNITS_PATH is checked and, if it exits 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.

utdec() decodes the formatted unit specification spec into a binary unit representation and stores the result in unit. The binary representation is used for algebraic manipulation. This function returns 0 on success, UT_ENOINIT if the package hasn't been initialized, UT_EUNKNOWN if the specification contains an unknown unit, and UT_ESYNTAX if the specification contains a syntax error.

utcaltime() 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.

uticaltime() 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.

utcvt() 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 variables is invalid, and UT_ECONVERT if the units are not convertable.

utenc() encodes the binary unit variable unit into a formatted unit specification and stores the string in spec. This function returns 0 on success, UT_ENOINIT if the package hasn't been initialized, UT_EINVALID if the unit variable is invalid, and UT_ENOROOM if the supplied character buffer is too small.

utclr() clears a unit variable by setting it to the dimensionless scalar 1.

uttime() returns 1 if the given unit variable refers to a time unit; 0 otherwise. This function ignores whether or not the unit has an origin.

utorigin() returns 1 if the given unit variable has an origin (i.e. defines a scale) and 0 otherwise.

utcpy() copies the unit variable source to the unit variable dest. This function correctly handles the case where the same unit variable is referenced by the source and destination units.

utscal() scales the unit variable source by the multiplicative scalar factor, storing the result in the unit variable result. This function correctly handles the case where the same unit variable is referenced by the source and result units.

utinv() inverts the unit variable source, storing the result in unit variable result. Multiplying a unit by its reciprocal yields the dimensionless scalar 1. This function correctly handles the case where the source and result unit refer to the same variable.

utdiv() divides unit variable numer by unit variable denom and stores the result in unit variable result. This function correctly handles the case where the same unit variable is referenced by two or more arguments.

utmult() multiplies unit variable term1 by unit variable term2 and stores the result in unit variable result. This function correctly handles the case where the same unit variable is referenced by two or more arguments.

utexp() raises the unit variable source by the power power, storing the result in the unit variable result. This function correctly handles the case where the same unit variable is referenced by the source and result units.

utcls() terminates usage of this package. In particular, it frees all allocated memory. It should be called when the library is no longer needed.

utmake() Creates a new unit variable. The value returned by this function may be used in subsequent calls. The unit variable is cleared by a call to utclr.

utfree() Frees the unit variable unit which was returned by a previous call to utmake().

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 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

In the following, it is assumed that a FORTRAN INTEGER data type is appropriate for storing a pointer to a C structure. This assumption is valid for most 32-bit architectures but is invalid for most 64-bit architectures that have 32-bit INTEGERs (e.g. a DEC Alpha).

Convert two data sets to a common unit, subtract one from the other, then save the result in a (different) output unit:

          INTEGER   UTOPEN
          ...
          IF (UTOPEN('') .NE. 0) THEN
    C         Handle initialization error
          ELSE
              CHARACTER*80        UNITSTRING1, UNITSTRING2
              CHARACTER*80        OUTPUTUNITSTRING
              INTEGER             UNIT1, UNIT2, OUTPUTUNIT
              INTEGER             UTMAKE, UTDEC
              ...
              UNIT1       = UTMAKE()
              UNIT2       = UTMAKE()
              OUTPUTUNIT  = UTMAKE()
              IF (UTDEC(UNITSTRING1, UNIT1) .NE. 0 .OR.
         *        UTDEC(UNITSTRING2, UNIT2) .NE. 0 .OR.
         *        UTDEC(OUTPUTUNITSTRING2, OUTPUTUNIT) .ne. 0) THEN
    C
    C             Handle decode error
    C
              ELSE
                  DOUBLEPRECISION INSLOPE, ININTERCEPT
                  DOUBLEPRECISION OUTSLOPE, OUTINTERCEPT
                  IF (UTCVT(UNIT2, UNIT1, INSLOPE, ININTERCEPT) .NE. 0
         *            .OR.  UTCVT(UNIT1, OUTPUTUNIT, OUTSLOPE,
         *                        OUTINTERCEPT) .NE. 0) THEN
    C
    C                 Handle data-incompatibility
    C
                  ELSE
    C                 Process data using:
    C                     OUTPUTVALUE = OUTSLOPE*(DATA1VALUE
    C                                   - (INSLOPE*DATA2VALUE
         *                                 + ININTERCEPT))
    C                                   + OUTINTERCEPT
                  ENDIF
                  CALL UTFREE(UNIT1)
                  CALL UTFREE(UNIT2)
                  CALL UTFREE(OUTPUTUNIT)
                  CALL UTCLS
              ENDIF
          ENDIF

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):

          INTEGER         INPUT_UNIT, DELTA_UNIT
          INTEGER         UTOPEN, UTMAKE, UTDEC
          CHARACTER*(80)  INPUT_UNIT_STRING, DELTA_UNIT_STRING
          ...
          INPUT_UNIT      = UTMAKE()
          DELTA_UNIT      = UTMAKE()
          CALL UTOPEN('udunits.dat')
          IF (UTDEC(INPUT_UNIT_STRING, INPUT_UNIT) .NE. 0 .OR.
              UTDEC(DELTA_UNIT_STRING, DELTA_UNIT) .NE. 0) THEN
    C
    C         Handle decode error
    C
          ELSE
              DOUBLEPRECISION     SLOPE, INTERCEPT
              REAL                DELTA_VALUE
              ...
              IF (UTCVT(DELTA_UNIT, INPUT_UNIT, SLOPE, INTERCEPT)
         *        .NE. 0) THEN
    C
    C             Handle units incompatibility
    C
              ELSE
                  REAL    INPUT_VALUE
                  REAL    THRESHOLD
                  ...
                  THRESHOLD = INPUT_VALUE + SLOPE*DELTA_VALUE + INTERCEPT
              ENDIF
          ENDIF
          CALL UTCLS

Compute the number of time intervals from a start time to a reference time. PTR is a placeholder for the FORTRAN data type equivalent to a memory address.

          IMPLICIT          NONE
          REAL              REF_SECOND      / 0 /
          INTEGER           UTOPEN
          INTEGER           UTDEC
          INTEGER           UTICALTIME
          INTEGER           STATUS
          INTEGER           REF_YEAR        / 1990 /
          INTEGER           REF_MONTH       / 1 /
          INTEGER           REF_DAY         / 1 /
          INTEGER           REF_HOUR        / 1 /
          INTEGER           REF_MINUTE      / 0 /
          INTEGER           UTMAKE
          INTEGER           TIMECENTERS_UNIT
          DOUBLEPRECISION   REF_VALUE
          STATUS = UTOPEN('udunits.dat')
          IF (STATUS .NE. 0) THEN
              PRINT *, 'Couldn''t open database: status =', STATUS
              CALL ABORT
          ENDIF
          TIMECENTERS_UNIT = UTMAKE()
          STATUS = UTDEC('2 minutes since 1990-1-1', TIMECENTERS_UNIT)
          IF (STATUS .NE. 0)
         *THEN
              PRINT *, 'UTDEC() =', STATUS
          ELSE
    C
    C         Reference time is start time plus 1 hour.
    C
              STATUS = UTICALTIME(REF_YEAR, REF_MONTH, REF_DAY, REF_HOUR,
         *                    REF_MINUTE, REF_SECOND, TIMECENTERS_UNIT,
         *                    REF_VALUE)
    C
    C         Number of time intervals between start and reference times:
    C
              IF (STATUS .NE. 0) THEN
                  PRINT *, 'UTICALTIME() =', STATUS
              ELSE
                  IF (30 .NE. REF_VALUE) THEN
                      PRINT *, 'Incorrect result:', REF_VALUE
                  ELSE
                      PRINT *, 'Correct result'
                  ENDIF
              ENDIF
          ENDIF
          END

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 grouping 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 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:

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.

UNITS FILE

The units file is a formatted file containing unit definitions 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 constants).

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).