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