"Fossies" - the Fresh Open Source Software Archive

Member "udunits-2.2.28/lib/unitcore.c" (8 Dec 2020, 91806 Bytes) of package /linux/privat/udunits-2.2.28.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "unitcore.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.2.26_vs_2.2.28.

    1 /*
    2  * Copyright 2020 University Corporation for Atmospheric Research
    3  *
    4  * This file is part of the UDUNITS-2 package.  See the file COPYRIGHT
    5  * in the top-level source-directory of the package for copying and
    6  * redistribution conditions.
    7  */
    8 /*
    9  * Unit creation and manipulation routines for the udunits(3) library.
   10  *
   11  * The following data-structures exist in this module:
   12  *  BasicUnit   Like an ISO "base unit" but also for dimensionless
   13  *          units (e.g., "radian").
   14  *  ProductUnit A unit that, when it is created, contains all the
   15  *          BasicUnit-s that exist at the time, each raised
   16  *          to an integral power (that can be zero).
   17  *  GalileanUnit    A unit whose value is related to another unit by a
   18  *          Galilean transformation (y = ax + b). Examples include
   19  *          "yard" and "degrees Fahrenheit".
   20  *  LogUnit     A unit that is related to another unit by a logarithmic
   21  *          transformation (y = a*log(x)).  The "Bel" is an example.
   22  *  TimestampUnit   A wrong-headed unit that shouldn't exist but does for
   23  *          backward compatibility.  It was intended to provide
   24  *          similar functionality as the GalileanUnit, but for time
   25  *          units (e.g., "seconds since the epoch").  Unfortunately,
   26  *          people try to use it for more than it is capable (e.g.,
   27  *          days since some time on an imaginary world with only 360
   28  *          days per year).
   29  *  ut_unit     A data-structure that encapsulates ProductUnit,
   30  *          GalileanUnit, LogUnit, and TimestampUnit.
   31  *
   32  * This module is thread-compatible but not thread-safe: multi-thread access to
   33  * this module must be externally synchronized.
   34  */
   35 
   36 /*LINTLIBRARY*/
   37 
   38 #include "config.h"
   39 
   40 #include "udunits2.h"       /* this module's API */
   41 #include "converter.h"
   42 
   43 #include <assert.h>
   44 #include <ctype.h>
   45 #include <errno.h>
   46 #include <float.h>
   47 #ifndef _MSC_VER
   48 #include <inttypes.h>
   49 #else
   50 #define int32_t __int32
   51 #endif
   52 
   53 #ifdef _MSC_VER
   54 #define _USE_MATH_DEFINES
   55 #endif
   56 
   57 #include <limits.h>
   58 #include <math.h>
   59 
   60 #ifdef _MSC_VER
   61 #include "tsearch.h"
   62 #else
   63 #include <search.h>
   64 #endif
   65 
   66 #include <stdbool.h>
   67 #include <stddef.h>
   68 #include <stdio.h>
   69 #include <stdlib.h>
   70 #include <string.h>
   71 #ifndef _MSC_VER
   72 
   73 #include <strings.h>
   74 #endif
   75 
   76 typedef enum {
   77     PRODUCT_EQUAL = 0,      /* The units are equal -- ignoring dimensionless
   78                  * basic-units */
   79     PRODUCT_INVERSE,        /* The units are reciprocals of each other */
   80     PRODUCT_UNCONVERTIBLE,  /* The units have incompatible dimensionality */
   81     PRODUCT_UNKNOWN     /* The relationship is unknown */
   82 } ProductRelationship;
   83 
   84 typedef struct BasicUnit    BasicUnit;
   85 typedef struct ProductUnit  ProductUnit;
   86 
   87 struct ut_system {
   88     ut_unit*        second;
   89     ut_unit*        one;        /* the dimensionless-unit one */
   90     BasicUnit**     basicUnits;
   91     int         basicCount;
   92 };
   93 
   94 typedef struct {
   95     ProductUnit*    (*getProduct)(const ut_unit*);
   96     ut_unit*        (*clone)(const ut_unit*);
   97     void        (*free)(ut_unit*);
   98     /*
   99      * The following comparison function is called if and only if the two units
  100      * belong to the same unit system.
  101      */
  102     int         (*compare)(const ut_unit*, const ut_unit*);
  103     ut_unit*        (*multiply)(const ut_unit*, const ut_unit*);
  104     ut_unit*        (*raise)(const ut_unit*, const int power);
  105     ut_unit*        (*root)(const ut_unit*, const int root);
  106     int         (*initConverterToProduct)(ut_unit*);
  107     int         (*initConverterFromProduct)(ut_unit*);
  108     ut_status       (*acceptVisitor)(const ut_unit*, const ut_visitor*,
  109                 void*);
  110 } UnitOps;
  111 
  112 typedef enum {
  113     BASIC,
  114     PRODUCT,
  115     GALILEAN,
  116     LOG,
  117     TIMESTAMP
  118 } UnitType;
  119 
  120 #undef  ABS
  121 #define ABS(a)      ((a) < 0 ? -(a) : (a))
  122 #undef  MIN
  123 #define MIN(a,b)    ((a) < (b) ? (a) : (b))
  124 #undef  MAX
  125 #define MAX(a,b)    ((a) > (b) ? (a) : (b))
  126 
  127 #define GET_PRODUCT(unit) \
  128             ((unit)->common.ops->getProduct(unit))
  129 #define CLONE(unit) ((unit)->common.ops->clone(unit))
  130 #define MULTIPLY(unit1, unit2) \
  131             ((unit1)->common.ops->multiply(unit1, unit2))
  132 #define RAISE(unit, power) \
  133             ((unit)->common.ops->raise(unit, power))
  134 #define ROOT(unit, root) \
  135             ((unit)->common.ops->root(unit, root))
  136 #define FREE(unit)  ((unit)->common.ops->free(unit))
  137 #define COMPARE(unit1, unit2) \
  138             ((unit1)->common.ops->compare(unit1, unit2))
  139 #define ENSURE_CONVERTER_TO_PRODUCT(unit) \
  140             ((unit)->common.toProduct != NULL || \
  141             (unit)->common.ops->initConverterToProduct(unit) == 0)
  142 #define ENSURE_CONVERTER_FROM_PRODUCT(unit) \
  143             ((unit)->common.fromProduct != NULL || \
  144             (unit)->common.ops->initConverterFromProduct(unit) == 0)
  145 #define ACCEPT_VISITOR(unit, visitor, arg) \
  146             ((unit)->common.ops->acceptVisitor(unit, visitor, arg))
  147 
  148 typedef struct {
  149     ut_system*      system;
  150     const UnitOps*  ops;
  151     UnitType        type;
  152     cv_converter*   toProduct;
  153     cv_converter*   fromProduct;
  154 } Common;
  155 
  156 struct BasicUnit {
  157     Common      common;
  158     ProductUnit*    product;        /* equivalent product-unit */
  159     int         index;          /* system->basicUnits index */
  160     int         isDimensionless;
  161 };
  162 
  163 struct ProductUnit {
  164     Common      common;
  165     short*      indexes;
  166     short*      powers;
  167     int         count;
  168 };
  169 
  170 typedef struct {
  171     Common      common;
  172     ut_unit*        unit;
  173     double      scale;
  174     double      offset;
  175 } GalileanUnit;
  176 
  177 typedef struct {
  178     Common      common;
  179     ut_unit*        unit;
  180     double      origin;
  181 } TimestampUnit;
  182 
  183 typedef struct {
  184     Common      common;
  185     ut_unit*        reference;
  186     double      base;
  187 } LogUnit;
  188 
  189 union ut_unit {
  190     Common      common;
  191     BasicUnit       basic;
  192     ProductUnit     product;
  193     GalileanUnit    galilean;
  194     TimestampUnit   timestamp;
  195     LogUnit     log;
  196 };
  197 
  198 #define IS_BASIC(unit)      ((unit)->common.type == BASIC)
  199 #define IS_PRODUCT(unit)    ((unit)->common.type == PRODUCT)
  200 #define IS_GALILEAN(unit)   ((unit)->common.type == GALILEAN)
  201 #define IS_LOG(unit)        ((unit)->common.type == LOG)
  202 #define IS_TIMESTAMP(unit)  ((unit)->common.type == TIMESTAMP)
  203 
  204 static bool areAlmostEqual(
  205         double x,
  206         double y)
  207 {
  208     return (x == 0 || y == 0)
  209     ? fabs(x - y) < 10*DBL_EPSILON
  210     : fabs(1.0 - x / y) < 10*DBL_EPSILON;
  211 }
  212 
  213 /*
  214  * The following function are declared here because they are used in the
  215  * basic-unit section  before they are defined in the product-unit section.
  216  */
  217 static ProductUnit* productNew(
  218     ut_system* const        system,
  219     const short* const      indexes,
  220     const short* const      powers,
  221     const int           count);
  222 static void     productFree(
  223     ut_unit* const      unit);
  224 static ut_unit*     productMultiply(
  225     const ut_unit* const    unit1,
  226     const ut_unit* const    unit2);
  227 static ut_unit*     productRaise(
  228     const ut_unit* const    unit,
  229     const int           power);
  230 static ut_unit*     productRoot(
  231     const ut_unit* const    unit,
  232     const int           root);
  233 
  234 
  235 /*
  236  * The following two functions convert between Julian day number and
  237  * Gregorian/Julian dates (Julian dates are used prior to October 15,
  238  * 1582; Gregorian dates are used after that).  Julian day number 0 is
  239  * midday, January 1, 4713 BCE.  The Gregorian calendar was adopted
  240  * midday, October 15, 1582.
  241  *
  242  * Author: Robert Iles, March 1994
  243  *
  244  * C Porter: Steve Emmerson, October 1995
  245  *
  246  * Original: http://www.nag.co.uk:70/nagware/Examples/calendar.f90
  247  *
  248  * There is no warranty on this code.
  249  */
  250 
  251 
  252 /*
  253  * Convert a Julian day number to a Gregorian/Julian date.
  254  */
  255 void
  256 julianDayToGregorianDate(julday, year, month, day)
  257     long    julday;     /* Julian day number to convert */
  258     int     *year;      /* Gregorian year (out) */
  259     int     *month;     /* Gregorian month (1-12) (out) */
  260     int     *day;       /* Gregorian day (1-31) (out) */
  261 {
  262     long    ja, jb, jd;
  263     int     jc;
  264     int     je, iday, imonth, iyear;
  265     double  xc;
  266 
  267     if (julday < 2299161)
  268     ja = julday;
  269     else
  270     {
  271     int ia = (int)(((julday - 1867216) - 0.25) / 36524.25);
  272 
  273     ja = julday + 1 + ia - (int)(0.25 * ia);
  274     }
  275 
  276     jb = ja + 1524;
  277     xc = ((jb - 2439870) - 122.1) / 365.25;
  278     jc = (int)(6680.0 + xc);
  279     jd = 365 * jc + (int)(0.25 * jc);
  280     je = (int)((jb - jd) / 30.6001);
  281 
  282     iday = (int)(jb - jd - (int)(30.6001 * je));
  283 
  284     imonth = je - 1;
  285     if (imonth > 12)
  286     imonth -= 12;
  287 
  288     iyear = jc - 4715;
  289     if (imonth > 2)
  290     iyear -= 1;
  291     if (iyear <= 0)
  292     iyear -= 1;
  293 
  294     *year = iyear;
  295     *month = imonth;
  296     *day = iday;
  297 }
  298 
  299 
  300 /*
  301  * Convert a Gregorian/Julian date to a Julian day number.
  302  *
  303  * The Gregorian calendar was adopted midday, October 15, 1582.
  304  */
  305 long
  306 gregorianDateToJulianDay(year, month, day)
  307     int     year;   /* Gregorian year */
  308     int     month;  /* Gregorian month (1-12) */
  309     int     day;    /* Gregorian day (1-31) */
  310 {
  311     int32_t igreg = 15 + 31 * (10 + (12 * 1582));
  312     int32_t iy; /* signed, origin 0 year */
  313     int32_t ja; /* Julian century */
  314     int32_t jm; /* Julian month */
  315     int32_t jy; /* Julian year */
  316     long    julday; /* returned Julian day number */
  317 
  318     /*
  319      * Because there is no 0 BC or 0 AD, assume the user wants the start of
  320      * the common era if they specify year 0.
  321      */
  322     if (year == 0)
  323     year = 1;
  324 
  325     iy = year;
  326     if (year < 0)
  327     iy++;
  328     if (month > 2)
  329     {
  330     jy = iy;
  331     jm = month + 1;
  332     }
  333     else
  334     {
  335     jy = iy - 1;
  336     jm = month + 13;
  337     }
  338 
  339     /*
  340      *  Note: SLIGHTLY STRANGE CONSTRUCTIONS REQUIRED TO AVOID PROBLEMS WITH
  341      *        OPTIMISATION OR GENERAL ERRORS UNDER VMS!
  342      */
  343     julday = day + (int)(30.6001 * jm);
  344     if (jy >= 0)
  345     {
  346     julday += 365 * jy;
  347     julday += (long)(0.25 * jy);
  348     }
  349     else
  350     {
  351     double  xi = 365.25 * jy;
  352 
  353     if ((int)xi != xi)
  354         xi -= 1;
  355     julday += (int)xi;
  356     }
  357     julday += 1720995;
  358 
  359     if (day + (31* (month + (12 * iy))) >= igreg)
  360     {
  361     ja = jy/100;
  362     julday -= ja;
  363     julday += 2;
  364     julday += ja/4;
  365     }
  366 
  367     return julday;
  368 }
  369 
  370 /*
  371  * Returns the Julian day number that is the origin of all things temporal in
  372  * this module.
  373  *
  374  * Returns:
  375  *      The Julian day number that is the origin for time in this module.
  376  */
  377 static long
  378 getJuldayOrigin()
  379 {
  380     static long juldayOrigin;
  381 
  382     if (juldayOrigin == 0)
  383     juldayOrigin = gregorianDateToJulianDay(2001, 1, 1);
  384 
  385     return juldayOrigin;
  386 }
  387 
  388 
  389 /*
  390  * Encodes a time as a double-precision value.
  391  *
  392  * Arguments:
  393  *  hours       The number of hours (0 = midnight).
  394  *  minutes     The number of minutes.
  395  *  seconds     The number of seconds.
  396  * Returns:
  397  *  The clock-time encoded as a scalar value.
  398  */
  399 double
  400 ut_encode_clock(
  401     int     hours,
  402     int     minutes,
  403     double  seconds)
  404 {
  405     if (abs(hours) >= 24 || abs(minutes) >= 60 || fabs(seconds) > 62) {
  406         ut_set_status(UT_BAD_ARG);
  407         return 0;
  408     }
  409 
  410     return (hours*60 + minutes)*60 + seconds;
  411 }
  412 
  413 inline static int
  414 mydiv(  const double   numer,
  415         const unsigned denom,
  416         double* const  rem)
  417 {
  418     int n = abs((int)numer)/denom;
  419     if (numer < 0)
  420         n = -n;
  421     *rem = numer - (long)n * (long)denom;
  422     return n;
  423 }
  424 
  425 static void
  426 decomp( double        value,
  427         int* const    days,
  428         int* const    hours,
  429         int* const    minutes,
  430         double* const seconds)
  431 {
  432     double rem;
  433     *days = mydiv(value, 86400, &rem);
  434     *hours = mydiv(rem, 3600, &rem);
  435     *minutes = mydiv(rem, 60, seconds);
  436 }
  437 
  438 
  439 /*
  440  * Encodes a date as a double-precision value.
  441  *
  442  * Arguments:
  443  *  year        The year.
  444  *  month       The month.
  445  *  day     The day (1 = the first of the month).
  446  * Returns:
  447  *  The date encoded as a scalar value.
  448  */
  449 double
  450 ut_encode_date(
  451     int     year,
  452     int     month,
  453     int     day)
  454 {
  455     return 86400.0 *
  456     (gregorianDateToJulianDay(year, month, day) - getJuldayOrigin());
  457 }
  458 
  459 
  460 /*
  461  * Encodes a time as a double-precision value.  The convenience function is
  462  * equivalent to "ut_encode_date(year,month,day) +
  463  * ut_encode_clock(hour,minute,second)"
  464  *
  465  * Arguments:
  466  *  year    The year.
  467  *  month   The month.
  468  *  day The day.
  469  *  hour    The hour.
  470  *  minute  The minute.
  471  *  second  The second.
  472  * Returns:
  473  *  The time encoded as a scalar value.
  474  */
  475 double
  476 ut_encode_time(
  477     const int       year,
  478     const int       month,
  479     const int       day,
  480     const int       hour,
  481     const int       minute,
  482     const double    second)
  483 {
  484     return ut_encode_date(year, month, day) + ut_encode_clock(hour, minute, second);
  485 }
  486 
  487 
  488 /*
  489  * Decodes a time from a double-precision value.
  490  *
  491  * Arguments:
  492  *      value           The value to be decoded.
  493  *      year            Pointer to the variable to be set to the year.
  494  *      month           Pointer to the variable to be set to the month.
  495  *      day             Pointer to the variable to be set to the day.
  496  *      hour            Pointer to the variable to be set to the hour.
  497  *      minute          Pointer to the variable to be set to the minute.
  498  *      second          Pointer to the variable to be set to the second.
  499  *      resolution      Pointer to the variable to be set to the resolution
  500  *                      of the decoded time in seconds.
  501  */
  502 void
  503 ut_decode_time(
  504     double  value,
  505     int     *year,
  506     int     *month,
  507     int     *day,
  508     int     *hour,
  509     int     *minute,
  510     double  *second,
  511     double  *resolution)
  512 {
  513     int     days;
  514     int     hours;
  515     int     minutes;
  516     int     d;
  517     double  seconds;
  518     /* Uncertainty of input value */
  519     double  uncer = ldexp(value < 0 ? -value : value, -DBL_MANT_DIG);
  520 
  521     days = (int)floor(value/86400.0);
  522     // `long long` is necessary for dates like `1-01-01`
  523     value -= days * (long long)86400; /* make positive excess */
  524     decomp(value, &d, &hours, &minutes, &seconds);
  525     days += d;
  526 
  527     if (seconds >= 60) {
  528     seconds -= 60;
  529     ++minutes;
  530     }
  531     if (minutes >= 60) {
  532         minutes -= 60;
  533         ++hours;
  534     }
  535     if (hours >= 24) {
  536         hours -= 24;
  537         ++days;
  538     }
  539 
  540     *second = seconds;
  541     *minute = minutes;
  542     *hour = hours;
  543     *resolution = uncer;
  544 
  545     julianDayToGregorianDate(getJuldayOrigin() + days, year, month, day);
  546 }
  547 
  548 
  549 /******************************************************************************
  550  * Parameters common to all types of units:
  551  ******************************************************************************/
  552 
  553 
  554 /*
  555  * Arguments:
  556  *  common  Pointer to unit common-area.
  557  *  ops Pointer to unit-specific function-structure.
  558  *  system  Pointer to unit-system.
  559  *  type    The type of unit.
  560  * Returns:
  561  *   0  Success.
  562  */
  563 static int
  564 commonInit(
  565     Common* const       common,
  566     const UnitOps* const    ops,
  567     const ut_system* const  system,
  568     const UnitType      type)
  569 {
  570     assert(system != NULL);
  571     assert(common != NULL);
  572     assert(ops != NULL);
  573 
  574     common->system = (ut_system*)system;
  575     common->ops = ops;
  576     common->type = type;
  577     common->toProduct = NULL;
  578     common->fromProduct = NULL;
  579 
  580     return 0;
  581 }
  582 
  583 
  584 /******************************************************************************
  585  * Basic-Unit:
  586  ******************************************************************************/
  587 
  588 
  589 static UnitOps  basicOps;
  590 
  591 
  592 /*
  593  * Returns a new instance of a basic-unit.
  594  *
  595  * Arguments:
  596  *  system      The unit-system to be associated with the new instance.
  597  *  isDimensionless Whether or not the unit is dimensionless (e.g.,
  598  *          "radian").
  599  *  index       The index of the basic-unit in "system".
  600  * Returns:
  601  *  NULL    Failure.  "ut_get_status()" will be:
  602  *          UT_OS   Operating-system error.  See "errno".
  603  *  else    Pointer to newly-allocated basic-unit.
  604  */
  605 static BasicUnit*
  606 basicNew(
  607     ut_system* const    system,
  608     const int       isDimensionless,
  609     const int       index)
  610 {
  611     BasicUnit*      basicUnit = NULL;   /* failure */
  612     int         error = 1;
  613     short       power = 1;
  614     short       shortIndex = (short)index;
  615     ProductUnit*    product;
  616 
  617     assert(system != NULL);
  618 
  619     product = productNew(system, &shortIndex, &power, 1);
  620 
  621     if (product == NULL) {
  622     ut_set_status(UT_OS);
  623     ut_handle_error_message(
  624         "basicNew(): Couldn't create new product-unit");
  625     }
  626     else {
  627     basicUnit = malloc(sizeof(BasicUnit));
  628 
  629     if (basicUnit == NULL) {
  630         ut_set_status(UT_OS);
  631         ut_handle_error_message(strerror(errno));
  632         ut_handle_error_message(
  633         "basicNew(): Couldn't allocate %lu-byte basic-unit",
  634         sizeof(BasicUnit));
  635     }
  636     else if (commonInit(&basicUnit->common, &basicOps, system,
  637         BASIC) == 0) {
  638         basicUnit->index = index;
  639         basicUnit->isDimensionless = isDimensionless;
  640         basicUnit->product = product;
  641         error = 0;                  // Success
  642     }               /* "basicUnit" allocated */
  643 
  644     if (error)
  645         productFree((ut_unit*)product);
  646     }               /* "product" allocated */
  647 
  648     return basicUnit;
  649 }
  650 
  651 
  652 static ProductUnit*
  653 basicGetProduct(
  654     const ut_unit* const    unit)
  655 {
  656     assert(IS_BASIC(unit));
  657 
  658     return unit->basic.product;
  659 }
  660 
  661 
  662 static ut_unit*
  663 basicClone(
  664     const ut_unit* const    unit)
  665 {
  666     assert(IS_BASIC(unit));
  667 
  668     return (ut_unit*)basicNew(unit->common.system, unit->basic.isDimensionless,
  669     unit->basic.index);
  670 }
  671 
  672 
  673 static void
  674 basicFree(
  675     ut_unit* const  unit)
  676 {
  677     if (unit != NULL) {
  678     assert(IS_BASIC(unit));
  679     productFree((ut_unit*)unit->basic.product);
  680     unit->basic.product = NULL;
  681     free(unit);
  682     }
  683 }
  684 
  685 
  686 static int
  687 basicCompare(
  688     const ut_unit* const    unit1,
  689     const ut_unit* const    unit2)
  690 {
  691     int cmp;
  692 
  693     assert(unit1 != NULL);
  694     assert(IS_BASIC(unit1));
  695     assert(unit2 != NULL);
  696 
  697     if (IS_PRODUCT(unit2)) {
  698     cmp = -COMPARE(unit2, unit1);
  699     }
  700     else if (!IS_BASIC(unit2)) {
  701     int diff = unit1->common.type - unit2->common.type;
  702 
  703     cmp = diff < 0 ? -1 : diff == 0 ? 0 : 1;
  704     }
  705     else {
  706     int index1 = unit1->basic.index;
  707     int index2 = unit2->basic.index;
  708 
  709     cmp = index1 < index2 ? -1 : index1 == index2 ? 0 : 1;
  710     }
  711 
  712     return cmp;
  713 }
  714 
  715 
  716 /*
  717  * Multiplies a basic-unit by another unit.
  718  *
  719  * Arguments:
  720  *  unit1   The basic-unit.
  721  *  unit2   The other unit.
  722  * Returns:
  723  *  NULL    Failure.  "ut_get_status()" will be:
  724  *          UT_MEANINGLESS  The operation on the given units is
  725  *                  meaningless.
  726  *  else    The resulting unit.
  727  */
  728 static ut_unit*
  729 basicMultiply(
  730     const ut_unit* const    unit1,
  731     const ut_unit* const    unit2)
  732 {
  733     assert(unit1 != NULL);
  734     assert(unit2 != NULL);
  735     assert(IS_BASIC(unit1));
  736 
  737     return productMultiply((const ut_unit*)unit1->basic.product, unit2);
  738 }
  739 
  740 
  741 /*
  742  * Returns the result of raising a basic-unit to a power.
  743  *
  744  * Arguments:
  745  *  unit    The basic-unit.
  746  *  power   The power.
  747  * Returns:
  748  *  NULL    Failure.  "ut_get_status()" will be:
  749  *          UT_MEANINGLESS  The operation on the given unit is
  750  *                  meaningless.
  751  *  else    The resulting unit.
  752  */
  753 static ut_unit*
  754 basicRaise(
  755     const ut_unit* const    unit,
  756     const int           power)
  757 {
  758     assert(unit != NULL);
  759     assert(IS_BASIC(unit));
  760     assert(power != 0);
  761     assert(power != 1);
  762 
  763     return productRaise((ut_unit*)unit->basic.product, power);
  764 }
  765 
  766 
  767 /*
  768  * Returns the result of taking a root of a basic-unit.
  769  *
  770  * Arguments:
  771  *  unit    The basic-unit.
  772  *  root    The root to take.
  773  * Returns:
  774  *  NULL    Failure.  "ut_get_status()" will be:
  775  *          UT_MEANINGLESS  The operation on the given unit is
  776  *                  meaningless.
  777  *  else    The resulting unit.
  778  */
  779 static ut_unit*
  780 basicRoot(
  781     const ut_unit* const    unit,
  782     const int           root)
  783 {
  784     assert(unit != NULL);
  785     assert(IS_BASIC(unit));
  786     assert(root > 1);
  787 
  788     return productRoot((ut_unit*)unit->basic.product, root);
  789 }
  790 
  791 
  792 /*
  793  * Initializes the converter of numeric from the given product-unit to the
  794  * underlying product-unit (i.e., to itself).
  795  *
  796  * Arguments:
  797  *  unit    The product unit.
  798  * Returns:
  799  *   0  Success.
  800  */
  801 static int
  802 basicInitConverterToProduct(
  803     ut_unit* const  unit)
  804 {
  805     assert(unit != NULL);
  806     assert(IS_BASIC(unit));
  807 
  808     if (unit->common.toProduct == NULL)
  809     unit->common.toProduct = cv_get_trivial();
  810 
  811     return 0;
  812 }
  813 
  814 
  815 /*
  816  * Initializes the converter of numeric to the given product-unit from the
  817  * underlying product-unit (i.e., to itself).
  818  *
  819  * Arguments:
  820  *  unit    The product unit.
  821  * Returns:
  822  *   0  Success.
  823  */
  824 static int
  825 basicInitConverterFromProduct(
  826     ut_unit* const  unit)
  827 {
  828     assert(unit != NULL);
  829     assert(IS_BASIC(unit));
  830 
  831     if (unit->common.fromProduct == NULL)
  832     unit->common.fromProduct = cv_get_trivial();
  833 
  834     return 0;
  835 }
  836 
  837 
  838 static ut_status
  839 basicAcceptVisitor(
  840     const ut_unit* const        unit,
  841     const ut_visitor* const visitor,
  842     void* const         arg)
  843 {
  844     assert(unit != NULL);
  845     assert(IS_BASIC(unit));
  846     assert(visitor != NULL);
  847 
  848     return visitor->visit_basic(unit, arg);
  849 }
  850 
  851 
  852 static UnitOps  basicOps = {
  853     basicGetProduct,
  854     basicClone,
  855     basicFree,
  856     basicCompare,
  857     basicMultiply,
  858     basicRaise,
  859     basicRoot,
  860     basicInitConverterToProduct,
  861     basicInitConverterFromProduct,
  862     basicAcceptVisitor
  863 };
  864 
  865 
  866 /******************************************************************************
  867  * Product Unit:
  868  ******************************************************************************/
  869 
  870 static UnitOps  productOps;
  871 
  872 
  873 /*
  874  * Arguments:
  875  *  system  The unit-system for the new unit.
  876  *  indexes Pointer to array of indexes of basic-units.  May be freed upon
  877  *      return.
  878  *  powers  Pointer to array of powers.  Client may free upon return.
  879  *  count   The number of elements in "indexes" and "powers".  May be zero.
  880  * Returns:
  881  *  NULL    Failure.  "ut_get_status()" will be:
  882  *          UT_OS   Operating-system error.  See "errno".
  883  *  else    The newly-allocated, product-unit.
  884  */
  885 static ProductUnit*
  886 productNew(
  887     ut_system* const    system,
  888     const short* const  indexes,
  889     const short* const  powers,
  890     const int       count)
  891 {
  892     ProductUnit*    productUnit;
  893 
  894     assert(system != NULL);
  895     assert(count >= 0);
  896     assert(count == 0 || (indexes != NULL && powers != NULL));
  897 
  898     productUnit = malloc(sizeof(ProductUnit));
  899 
  900     if (productUnit == NULL) {
  901     ut_set_status(UT_OS);
  902     ut_handle_error_message(strerror(errno));
  903     ut_handle_error_message(
  904         "productNew(): Couldn't allocate %d-byte product-unit",
  905         sizeof(ProductUnit));
  906     }
  907     else {
  908     int error = 1;
  909 
  910     if (commonInit(&productUnit->common, &productOps, system, PRODUCT)
  911         == 0) {
  912             if (count == 0) {
  913                 productUnit->count = count;
  914                 productUnit->indexes = NULL;
  915                 productUnit->powers = NULL;
  916                 error = 0;
  917             }
  918             else {
  919                 size_t  nbytes = sizeof(short)*count;
  920                 short*  newIndexes = malloc(nbytes*2);
  921 
  922                 if (count > 0 && newIndexes == NULL) {
  923                     ut_set_status(UT_OS);
  924                     ut_handle_error_message(strerror(errno));
  925                     ut_handle_error_message("productNew(): "
  926                         "Couldn't allocate %d-element index array", count);
  927                 }
  928                 else {
  929                     short*  newPowers = newIndexes + count;
  930 
  931                     productUnit->count = count;
  932                     productUnit->indexes = memcpy(newIndexes, indexes, nbytes);
  933                     productUnit->powers = memcpy(newPowers, powers, nbytes);
  934                     error = 0;
  935                 }
  936         }                           /* "count > 0" */
  937     }                               /* "productUnit->common" initialized */
  938 
  939     if (error) {
  940         free(productUnit);
  941         productUnit = NULL;
  942     }
  943     }                       /* "productUnit" allocated */
  944 
  945     return productUnit;
  946 }
  947 
  948 
  949 static ProductUnit*
  950 productGetProduct(
  951     const ut_unit* const    unit)
  952 {
  953     assert(unit != NULL);
  954     assert(IS_PRODUCT(unit));
  955 
  956     return (ProductUnit*)&unit->product;
  957 }
  958 
  959 
  960 static ut_unit*
  961 productClone(
  962     const ut_unit* const    unit)
  963 {
  964     ut_unit*        clone;
  965 
  966     assert(unit != NULL);
  967     assert(IS_PRODUCT(unit));
  968 
  969     if (unit == unit->common.system->one) {
  970     clone = unit->common.system->one;
  971     }
  972     else {
  973     clone = (ut_unit*)productNew(unit->common.system,
  974         unit->product.indexes, unit->product.powers,
  975         unit->product.count);
  976     }
  977 
  978     return clone;
  979 }
  980 
  981 
  982 static int
  983 productCompare(
  984     const ut_unit* const    unit1,
  985     const ut_unit* const    unit2)
  986 {
  987     int cmp;
  988 
  989     assert(unit1 != NULL);
  990     assert(IS_PRODUCT(unit1));
  991     assert(unit2 != NULL);
  992 
  993     if (IS_BASIC(unit2)) {
  994     cmp = productCompare(unit1, (ut_unit*)unit2->basic.product);
  995     }
  996     else if (!IS_PRODUCT(unit2)) {
  997     int diff = unit1->common.type - unit2->common.type;
  998 
  999     cmp = diff < 0 ? -1 : diff == 0 ? 0 : 1;
 1000     }
 1001     else {
 1002     const ProductUnit* const    product1 = &unit1->product;
 1003     const ProductUnit* const    product2 = &unit2->product;
 1004 
 1005         cmp = product1->count - product2->count;
 1006 
 1007         if (cmp == 0) {
 1008         const short* const  indexes1 = product1->indexes;
 1009         const short* const  indexes2 = product2->indexes;
 1010         const short* const  powers1 = product1->powers;
 1011         const short* const  powers2 = product2->powers;
 1012         int         i;
 1013 
 1014         for (i = 0; i < product1->count; ++i) {
 1015         cmp = indexes1[i] - indexes2[i];
 1016 
 1017         if (cmp == 0)
 1018             cmp = powers1[i] - powers2[i];
 1019 
 1020         if (cmp != 0)
 1021             break;
 1022         }
 1023     }
 1024     }
 1025 
 1026     return cmp;
 1027 }
 1028 
 1029 
 1030 static void
 1031 productReallyFree(
 1032     ut_unit* const  unit)
 1033 {
 1034     if (unit != NULL) {
 1035     assert(IS_PRODUCT(unit));
 1036     free(unit->product.indexes);
 1037     unit->product.indexes = NULL;
 1038     cv_free(unit->common.toProduct);
 1039     unit->common.toProduct = NULL;
 1040     cv_free(unit->common.fromProduct);
 1041     unit->common.fromProduct = NULL;
 1042     free(unit);
 1043     }
 1044 }
 1045 
 1046 
 1047 static void
 1048 productFree(
 1049     ut_unit* const  unit)
 1050 {
 1051     if (unit != unit->common.system->one)
 1052     productReallyFree(unit);
 1053 }
 1054 
 1055 
 1056 /*
 1057  * Multiplies a product-unit by another unit.
 1058  *
 1059  * Arguments:
 1060  *  unit1   The product unit.
 1061  *  unit2   The other unit.
 1062  * Returns:
 1063  *  NULL    Failure.  "ut_get_status()" will be:
 1064  *          UT_MEANINGLESS  The operation on the given units is
 1065  *                  meaningless.
 1066  *          UT_OS       Operating-system failure.  See "errno".
 1067  *  else    The resulting unit.
 1068  */
 1069 static ut_unit*
 1070 productMultiply(
 1071     const ut_unit* const    unit1,
 1072     const ut_unit* const    unit2)
 1073 {
 1074     ut_unit*        result = NULL;  /* failure */
 1075 
 1076     assert(unit1 != NULL);
 1077     assert(unit2 != NULL);
 1078     assert(IS_PRODUCT(unit1));
 1079 
 1080     if (!IS_PRODUCT(unit2)) {
 1081     result = MULTIPLY(unit2, unit1);
 1082     }
 1083     else {
 1084     const ProductUnit* const    product1 = &unit1->product;
 1085     const ProductUnit* const    product2 = &unit2->product;
 1086     short*              indexes1 = product1->indexes;
 1087     short*              indexes2 = product2->indexes;
 1088     short*              powers1 = product1->powers;
 1089     short*              powers2 = product2->powers;
 1090     int             count1 = product1->count;
 1091     int             count2 = product2->count;
 1092     int             sumCount = count1 + count2;
 1093 
 1094     if (sumCount == 0) {
 1095         result = unit1->common.system->one;
 1096     }
 1097     else {
 1098         static short*       indexes = NULL;
 1099 
 1100         indexes = realloc(indexes, sizeof(short)*sumCount);
 1101 
 1102         if (indexes == NULL) {
 1103         ut_set_status(UT_OS);
 1104         ut_handle_error_message(strerror(errno));
 1105         ut_handle_error_message("productMultiply(): "
 1106             "Couldn't allocate %d-element index array", sumCount);
 1107         }
 1108         else {
 1109         static short*   powers = NULL;
 1110 
 1111         powers = realloc(powers, sizeof(short)*sumCount);
 1112 
 1113         if (powers == NULL) {
 1114             ut_set_status(UT_OS);
 1115             ut_handle_error_message(strerror(errno));
 1116             ut_handle_error_message("productMultiply(): "
 1117             "Couldn't allocate %d-element power array",
 1118             sumCount);
 1119         }
 1120         else {
 1121             int             count = 0;
 1122             int             i1 = 0;
 1123             int             i2 = 0;
 1124 
 1125             while (i1 < count1 || i2 < count2) {
 1126             if (i1 >= count1) {
 1127                 indexes[count] = indexes2[i2];
 1128                 powers[count++] = powers2[i2++];
 1129             }
 1130             else if (i2 >= count2) {
 1131                 indexes[count] = indexes1[i1];
 1132                 powers[count++] = powers1[i1++];
 1133             }
 1134             else if (indexes1[i1] > indexes2[i2]) {
 1135                 indexes[count] = indexes2[i2];
 1136                 powers[count++] = powers2[i2++];
 1137             }
 1138             else if (indexes1[i1] < indexes2[i2]) {
 1139                 indexes[count] = indexes1[i1];
 1140                 powers[count++] = powers1[i1++];
 1141             }
 1142             else {
 1143                 if (powers1[i1] != -powers2[i2]) {
 1144                 indexes[count] = indexes1[i1];
 1145                 powers[count++] = powers1[i1] + powers2[i2];
 1146                 }
 1147 
 1148                 i1++;
 1149                 i2++;
 1150             }
 1151             }
 1152 
 1153             result = (ut_unit*)productNew(unit1->common.system,
 1154             indexes, powers, count);
 1155         }           /* "powers" re-allocated */
 1156         }               /* "indexes" re-allocated */
 1157     }               /* "sumCount > 0" */
 1158     }                   /* "unit2" is a product-unit */
 1159 
 1160     return result;
 1161 }
 1162 
 1163 
 1164 /*
 1165  * Returns the result of raising a product unit to a power.
 1166  *
 1167  * Arguments:
 1168  *  unit    The product unit.
 1169  *  power   The power.  Must be greater than -256 and less than 256.
 1170  * Returns:
 1171  *  NULL    Failure.  "ut_get_status()" will be:
 1172  *          UT_MEANINGLESS  The operation on the given unit is
 1173  *                  meaningless.
 1174  *  else    The resulting unit.
 1175  */
 1176 static ut_unit*
 1177 productRaise(
 1178     const ut_unit* const    unit,
 1179     const int           power)
 1180 {
 1181     ut_unit*        result = NULL;  /* failure */
 1182     const ProductUnit*  product;
 1183     int         count;
 1184     short*      newPowers;
 1185 
 1186     assert(unit != NULL);
 1187     assert(IS_PRODUCT(unit));
 1188     assert(power >= -255 && power <= 255);
 1189     assert(power != 0);
 1190     assert(power != 1);
 1191 
 1192     product = &unit->product;
 1193     count = product->count;
 1194 
 1195     if (count == 0) {
 1196         result = unit->common.system->one;
 1197     }
 1198     else {
 1199         newPowers = malloc(sizeof(short)*count);
 1200 
 1201         if (newPowers == NULL) {
 1202             ut_set_status(UT_OS);
 1203             ut_handle_error_message(strerror(errno));
 1204             ut_handle_error_message("productRaise(): "
 1205                 "Couldn't allocate %d-element powers-buffer", count);
 1206         }
 1207         else {
 1208             const short* const  oldPowers = product->powers;
 1209             int         i;
 1210 
 1211             for (i = 0; i < count; i++)
 1212                 newPowers[i] = (short)(oldPowers[i] * power);
 1213 
 1214             result = (ut_unit*)productNew(unit->common.system,
 1215                 product->indexes, newPowers, count);
 1216 
 1217             free(newPowers);
 1218         }               /* "newPowers" allocated */
 1219     }                       /* "count > 0" */
 1220 
 1221     return result;
 1222 }
 1223 
 1224 
 1225 /*
 1226  * Returns the result of taking a root of a unit.
 1227  *
 1228  * Arguments:
 1229  *  unit    The product unit.
 1230  *  root    The root.  Must be greater than 1 and less than 256.
 1231  * Returns:
 1232  *  NULL    Failure.  "ut_get_status()" will be:
 1233  *          UT_MEANINGLESS  The operation on the given unit is
 1234  *                  meaningless.
 1235  *  else    The resulting unit.
 1236  */
 1237 static ut_unit*
 1238 productRoot(
 1239     const ut_unit* const    unit,
 1240     const int           root)
 1241 {
 1242     ut_unit*        result = NULL;  /* failure */
 1243     const ProductUnit*  product;
 1244     int         count;
 1245     short*      newPowers;
 1246 
 1247     assert(unit != NULL);
 1248     assert(IS_PRODUCT(unit));
 1249     assert(root > 1 && root <= 255);
 1250 
 1251     product = &unit->product;
 1252     count = product->count;
 1253 
 1254     if (count == 0) {
 1255         result = unit->common.system->one;
 1256     }
 1257     else {
 1258         newPowers = malloc(sizeof(short)*count);
 1259 
 1260         if (newPowers == NULL) {
 1261             ut_set_status(UT_OS);
 1262             ut_handle_error_message(strerror(errno));
 1263             ut_handle_error_message("productRoot(): "
 1264                 "Couldn't allocate %d-element powers-buffer", count);
 1265         }
 1266         else {
 1267             const short* const  oldPowers = product->powers;
 1268             int         i;
 1269 
 1270             for (i = 0; i < count; i++) {
 1271                 if ((oldPowers[i] % root) != 0) {
 1272                     break;
 1273                 }
 1274                 newPowers[i] = (short)(oldPowers[i] / root);
 1275             }
 1276 
 1277             if (i < count) {
 1278                 char buf[80];
 1279 
 1280                 if (ut_format(unit, buf, sizeof(buf), UT_ASCII) == -1) {
 1281                     ut_set_status(UT_MEANINGLESS);
 1282                     ut_handle_error_message("productRoot(): "
 1283                         "Can't take root of unit");
 1284                 }
 1285                 else {
 1286                     ut_set_status(UT_MEANINGLESS);
 1287                     buf[sizeof(buf)-1] = 0;
 1288                     ut_handle_error_message("productRoot(): "
 1289                         "It's meaningless to take the %d%s root of \"%s\"",
 1290                         root, root == 2 ? "nd" : root == 3 ? "rd" : "th",
 1291                         buf);
 1292                 }
 1293             }
 1294             else {
 1295                 result = (ut_unit*)productNew(unit->common.system,
 1296                     product->indexes, newPowers, count);
 1297             }
 1298 
 1299             free(newPowers);
 1300         }               /* "newPowers" allocated */
 1301     }                       /* "count > 0" */
 1302 
 1303     return result;
 1304 }
 1305 
 1306 
 1307 /*
 1308  * Initializes a converter of numeric values between the given product-unit and
 1309  * the underlying product-unit (i.e., to itself).
 1310  *
 1311  * Arguments:
 1312  *  converter   Pointer to pointer to the converter to be initialized.
 1313  * Returns:
 1314  *   0  Success.
 1315  */
 1316 static int
 1317 productInitConverter(
 1318     cv_converter** const    converter)
 1319 {
 1320     assert(converter != NULL);
 1321 
 1322     *converter = cv_get_trivial();
 1323 
 1324     return 0;
 1325 }
 1326 
 1327 
 1328 /*
 1329  * Initializes the converter of numeric values from the given product-unit to
 1330  * the underlying product-unit (i.e., to itself).
 1331  *
 1332  * Arguments:
 1333  *  unit    The product unit.
 1334  * Returns:
 1335  *   0  Success.
 1336  */
 1337 static int
 1338 productInitConverterToProduct(
 1339     ut_unit* const  unit)
 1340 {
 1341     assert(unit != NULL);
 1342     assert(IS_PRODUCT(unit));
 1343 
 1344     return productInitConverter(&unit->common.toProduct);
 1345 }
 1346 
 1347 
 1348 /*
 1349  * Initializes the converter of numeric values to the given product-unit from
 1350  * the underlying product-unit (i.e., to itself).
 1351  *
 1352  * Arguments:
 1353  *  unit    The product unit.
 1354  * Returns:
 1355  *   0  Success.
 1356  */
 1357 static int
 1358 productInitConverterFromProduct(
 1359     ut_unit* const  unit)
 1360 {
 1361     assert(unit != NULL);
 1362     assert(IS_PRODUCT(unit));
 1363 
 1364     return productInitConverter(&unit->common.fromProduct);
 1365 }
 1366 
 1367 
 1368 /*
 1369  * Returns the relationship between two product-units.  In determining the
 1370  * relationship, dimensionless basic-units are ignored.
 1371  *
 1372  * Arguments:
 1373  *  unit1   The first product unit.
 1374  *  unit2   The second product unit.
 1375  * Returns:
 1376  *  PRODUCT_EQUAL       The units are equal -- ignoring dimensionless
 1377  *              basic-units.
 1378  *  PRODUCT_INVERSE     The units are reciprocals of each other.
 1379  *  PRODUCT_UNCONVERTIBLE   The dimensionalities of the units are
 1380  *              unconvertible.
 1381  */
 1382 static ProductRelationship
 1383 productRelationship(
 1384     const ProductUnit* const    unit1,
 1385     const ProductUnit* const    unit2)
 1386 {
 1387     ProductRelationship     relationship = PRODUCT_UNKNOWN;
 1388 
 1389     assert(unit1 != NULL);
 1390     assert(unit2 != NULL);
 1391 
 1392     {
 1393     const short* const  indexes1 = unit1->indexes;
 1394     const short* const  indexes2 = unit2->indexes;
 1395     const short* const  powers1 = unit1->powers;
 1396     const short* const  powers2 = unit2->powers;
 1397     const int       count1 = unit1->count;
 1398     const int       count2 = unit2->count;
 1399     const ut_system* const  system = unit1->common.system;
 1400     int         i1 = 0;
 1401     int         i2 = 0;
 1402 
 1403     while (i1 < count1 || i2 < count2) {
 1404         int iBasic = -1;
 1405 
 1406         if (i1 >= count1) {
 1407         iBasic = indexes2[i2++];
 1408         }
 1409         else if (i2 >= count2) {
 1410         iBasic = indexes1[i1++];
 1411         }
 1412         else if (indexes1[i1] > indexes2[i2]) {
 1413         iBasic = indexes2[i2++];
 1414         }
 1415         else if (indexes1[i1] < indexes2[i2]) {
 1416         iBasic = indexes1[i1++];
 1417         }
 1418 
 1419         if (iBasic != -1) {
 1420         if (!system->basicUnits[iBasic]->isDimensionless) {
 1421             relationship = PRODUCT_UNCONVERTIBLE;
 1422             break;
 1423         }
 1424         }
 1425         else {
 1426         iBasic = indexes1[i1];
 1427 
 1428         if (!system->basicUnits[iBasic]->isDimensionless) {
 1429             if (powers1[i1] == powers2[i2]) {
 1430             if (relationship == PRODUCT_INVERSE) {
 1431                 relationship = PRODUCT_UNCONVERTIBLE;
 1432                 break;
 1433             }
 1434 
 1435             relationship = PRODUCT_EQUAL;
 1436             }
 1437             else if (powers1[i1] == -powers2[i2]) {
 1438             if (relationship == PRODUCT_EQUAL) {
 1439                 relationship = PRODUCT_UNCONVERTIBLE;
 1440                 break;
 1441             }
 1442 
 1443             relationship = PRODUCT_INVERSE;
 1444             }
 1445             else {
 1446             relationship = PRODUCT_UNCONVERTIBLE;
 1447             break;
 1448             }
 1449         }
 1450 
 1451         i1++;
 1452         i2++;
 1453         }
 1454     }
 1455     }
 1456 
 1457     if (relationship == PRODUCT_UNKNOWN) {
 1458     /*
 1459      * Both units are dimensionless.
 1460      */
 1461     relationship = PRODUCT_EQUAL;
 1462     }
 1463 
 1464     return relationship;
 1465 }
 1466 
 1467 
 1468 static ut_status
 1469 productAcceptVisitor(
 1470     const ut_unit* const    unit,
 1471     const ut_visitor* const visitor,
 1472     void* const         arg)
 1473 {
 1474     int     count = unit->product.count;
 1475     BasicUnit** basicUnits = malloc(sizeof(BasicUnit*)*count);
 1476 
 1477     assert(unit != NULL);
 1478     assert(IS_PRODUCT(unit));
 1479     assert(visitor != NULL);
 1480 
 1481     if (count != 0 && basicUnits == NULL) {
 1482     ut_set_status(UT_OS);
 1483     ut_handle_error_message(strerror(errno));
 1484     ut_handle_error_message("productAcceptVisitor(): "
 1485         "Couldn't allocate %d-element basic-unit array", count);
 1486     }
 1487     else {
 1488         int*    powers = (count > 0 ? malloc(sizeof(int)*count) : NULL);
 1489 
 1490     if (count != 0 && powers == NULL) {
 1491         ut_set_status(UT_OS);
 1492         ut_handle_error_message(strerror(errno));
 1493         ut_handle_error_message("productAcceptVisitor(): "
 1494         "Couldn't allocate %d-element power array", count);
 1495     }
 1496     else {
 1497         const ProductUnit*  prodUnit = &unit->product;
 1498         int         i;
 1499 
 1500         for (i = 0; i < count; ++i) {
 1501         basicUnits[i] =
 1502             unit->common.system->basicUnits[prodUnit->indexes[i]];
 1503         powers[i] = prodUnit->powers[i];
 1504         }
 1505 
 1506         ut_set_status(visitor->visit_product(unit, count,
 1507         (const ut_unit**)basicUnits, powers, arg));
 1508 
 1509             if (powers)
 1510                 free(powers);
 1511     }               /* "powers" allocated */
 1512 
 1513     free(basicUnits);
 1514     }                   /* "basicUnits" allocated */
 1515 
 1516     return ut_get_status();
 1517 }
 1518 
 1519 
 1520 static UnitOps  productOps = {
 1521     productGetProduct,
 1522     productClone,
 1523     productFree,
 1524     productCompare,
 1525     productMultiply,
 1526     productRaise,
 1527     productRoot,
 1528     productInitConverterToProduct,
 1529     productInitConverterFromProduct,
 1530     productAcceptVisitor
 1531 };
 1532 
 1533 
 1534 /*
 1535  * Indicates if a product-unit is dimensionless or not.
 1536  *
 1537  * Arguments:
 1538  *  unit    The product-unit in question.
 1539  * Returns:
 1540  *  0   "unit" is dimensionfull.
 1541  *  else    "unit" is dimensionless.
 1542  */
 1543 static int
 1544 productIsDimensionless(
 1545     const ProductUnit* const    unit)
 1546 {
 1547     int         isDimensionless = 1;
 1548     int         count;
 1549     const short*    indexes;
 1550     ut_system*      system;
 1551     int         i;
 1552 
 1553     assert(unit != NULL);
 1554     assert(IS_PRODUCT(unit));
 1555 
 1556     count = unit->count;
 1557     indexes = unit->indexes;
 1558     system = unit->common.system;
 1559 
 1560     for (i = 0; i < count; ++i) {
 1561     if (!system->basicUnits[indexes[i]]->isDimensionless) {
 1562         isDimensionless = 0;
 1563         break;
 1564     }
 1565     }
 1566 
 1567     return isDimensionless;
 1568 }
 1569 
 1570 
 1571 /******************************************************************************
 1572  * Galilean Unit:
 1573  ******************************************************************************/
 1574 
 1575 
 1576 static UnitOps  galileanOps;
 1577 
 1578 
 1579 /**
 1580  * Returns a new unit instance.  The returned instance is not necessarily a
 1581  * Galilean unit.
 1582  *
 1583  * @param[in] scale The scale-factor for the new unit.
 1584  * @param[in] unit  The underlying unit.  May be freed upon return.
 1585  * @param[in] offset    The offset for the new unit.
 1586  * @retval    NULL  Failure.  `ut_get_status()` will be:
 1587  *                UT_OS Operating-system error.  See `errno`.
 1588  *                UT_BAD_ARG  `scale == 0 || unit == NULL`
 1589  * @return              The newly-allocated, galilean-unit.
 1590  */
 1591 static ut_unit*
 1592 galileanNew(
 1593     double      scale,
 1594     const ut_unit*  unit,
 1595     double      offset)
 1596 {
 1597     ut_unit*    newUnit;
 1598 
 1599     if (scale == 0 || unit == NULL) {
 1600         ut_set_status(UT_BAD_ARG);
 1601         newUnit = NULL;
 1602     }
 1603     else {
 1604         if (IS_GALILEAN(unit)) {
 1605             scale *= unit->galilean.scale;
 1606             offset += (unit->galilean.scale * unit->galilean.offset) / scale;
 1607             unit = unit->galilean.unit;
 1608         }
 1609 
 1610         if (areAlmostEqual(scale, 1) && areAlmostEqual(offset, 0)) {
 1611             newUnit = CLONE(unit);
 1612         }
 1613         else {
 1614             GalileanUnit*   galileanUnit = malloc(sizeof(GalileanUnit));
 1615 
 1616             if (galileanUnit == NULL) {
 1617                 ut_set_status(UT_OS);
 1618                 ut_handle_error_message("galileanNew(): "
 1619                     "Couldn't allocate %lu-byte Galilean unit",
 1620                     sizeof(GalileanUnit));
 1621             }
 1622             else {
 1623                 int error = 1;
 1624 
 1625                 if (commonInit(&galileanUnit->common, &galileanOps,
 1626                         unit->common.system, GALILEAN) == 0) {
 1627                     galileanUnit->scale = scale;
 1628                     galileanUnit->offset = offset;
 1629                     galileanUnit->unit = CLONE(unit);
 1630                     error = 0;
 1631                 }
 1632 
 1633                 if (error) {
 1634                     free(galileanUnit);
 1635                     galileanUnit = NULL;
 1636                 }
 1637             }               /* "galileanUnit" allocated */
 1638 
 1639             newUnit = (ut_unit*)galileanUnit;
 1640         }                   /* Galilean unit necessary */
 1641     } // `scale != 0 && unit != NULL`
 1642 
 1643     return newUnit;
 1644 }
 1645 
 1646 
 1647 static ProductUnit*
 1648 galileanGetProduct(
 1649     const ut_unit* const    unit)
 1650 {
 1651     assert(unit != NULL);
 1652     assert(IS_GALILEAN(unit));
 1653 
 1654     return GET_PRODUCT(unit->galilean.unit);
 1655 }
 1656 
 1657 
 1658 static ut_unit*
 1659 galileanClone(
 1660     const ut_unit* const    unit)
 1661 {
 1662     const GalileanUnit* galileanUnit;
 1663 
 1664     assert(unit != NULL);
 1665     assert(IS_GALILEAN(unit));
 1666 
 1667     galileanUnit = &unit->galilean;
 1668 
 1669     return galileanNew(galileanUnit->scale, galileanUnit->unit,
 1670     galileanUnit->offset);
 1671 }
 1672 
 1673 
 1674 static int
 1675 galileanCompare(
 1676     const ut_unit* const    unit1,
 1677     const ut_unit* const    unit2)
 1678 {
 1679     int cmp;
 1680 
 1681     assert(unit1 != NULL);
 1682     assert(IS_GALILEAN(unit1));
 1683 
 1684     if (!IS_GALILEAN(unit2)) {
 1685     int diff = unit1->common.type - unit2->common.type;
 1686 
 1687     cmp = diff < 0 ? -1 : diff == 0 ? 0 : 1;
 1688     }
 1689     else {
 1690     const GalileanUnit* const   galilean1 = &unit1->galilean;
 1691     const GalileanUnit* const   galilean2 = &unit2->galilean;
 1692 
 1693     cmp =
 1694         galilean1->offset < galilean2->offset
 1695         ? -1
 1696         : galilean1->offset == galilean2->offset
 1697             ? 0
 1698             : 1;
 1699 
 1700     if (cmp == 0) {
 1701         cmp =
 1702         galilean1->scale < galilean2->scale
 1703             ? -1
 1704             : galilean1->scale == galilean2->scale
 1705             ? 0
 1706             : 1;
 1707 
 1708         if (cmp == 0)
 1709         cmp = COMPARE(galilean1->unit, galilean2->unit);
 1710     }
 1711     }
 1712 
 1713     return cmp;
 1714 }
 1715 
 1716 
 1717 static void
 1718 galileanFree(
 1719     ut_unit* const  unit)
 1720 {
 1721     if (unit != NULL) {
 1722     assert(IS_GALILEAN(unit));
 1723     FREE(unit->galilean.unit);
 1724     cv_free(unit->common.toProduct);
 1725     unit->common.toProduct = NULL;
 1726     cv_free(unit->common.fromProduct);
 1727     unit->common.fromProduct = NULL;
 1728     free((void*)unit);
 1729     }
 1730 }
 1731 
 1732 
 1733 /*
 1734  * Multiplies a Galilean-unit by another unit.  Any offset is ignored.
 1735  *
 1736  * Arguments:
 1737  *  unit1   The Galilean-unit.
 1738  *  unit2   The other unit.
 1739  * Returns:
 1740  *  NULL    Failure.  "ut_get_status()" will be:
 1741  *          UT_MEANINGLESS  The operation on the given units is
 1742  *                  meaningless.
 1743  *  else    The resulting unit.
 1744  */
 1745 static ut_unit*
 1746 galileanMultiply(
 1747     const ut_unit* const    unit1,
 1748     const ut_unit* const    unit2)
 1749 {
 1750     ut_unit*        result = NULL;  /* failure */
 1751     const GalileanUnit* galilean1;
 1752 
 1753     assert(unit1 != NULL);
 1754     assert(unit2 != NULL);
 1755     assert(IS_GALILEAN(unit1));
 1756 
 1757     galilean1 = &unit1->galilean;
 1758 
 1759     if (IS_PRODUCT(unit2)) {
 1760     ut_unit*    tmp = MULTIPLY(galilean1->unit, unit2);
 1761 
 1762     if (tmp != NULL) {
 1763         result = galileanNew(galilean1->scale, tmp, 0);
 1764 
 1765         FREE(tmp);
 1766     }
 1767     }
 1768     else if (IS_GALILEAN(unit2)) {
 1769     const GalileanUnit* const galilean2 = &unit2->galilean;
 1770     ut_unit*              tmp =
 1771         MULTIPLY(galilean1->unit, galilean2->unit);
 1772 
 1773     if (tmp != NULL) {
 1774         result = galileanNew(galilean1->scale * galilean2->scale, tmp, 0);
 1775 
 1776         FREE(tmp);
 1777     }
 1778     }
 1779     else {
 1780     result = MULTIPLY(unit2, unit1);
 1781     }
 1782 
 1783     return result;
 1784 }
 1785 
 1786 
 1787 /*
 1788  * Returns the result of raising a Galilean-unit to a power.  Any offset is
 1789  * ignored.
 1790  *
 1791  * Arguments:
 1792  *  unit    The Galilean-unit.
 1793  *  power   The power.  Must be greater than -256 and less than 256.
 1794  * Returns:
 1795  *  NULL    Failure.  "ut_get_status()" will be:
 1796  *          UT_MEANINGLESS  The operation on the given units is
 1797  *                  meaningless.
 1798  *  else    The resulting unit.
 1799  */
 1800 static ut_unit*
 1801 galileanRaise(
 1802     const ut_unit* const    unit,
 1803     const int           power)
 1804 {
 1805     const GalileanUnit*  galilean;
 1806     ut_unit*             tmp;
 1807     ut_unit*             result = NULL;  /* failure */
 1808 
 1809     assert(unit != NULL);
 1810     assert(IS_GALILEAN(unit));
 1811     assert(power >= -255 && power <= 255);
 1812     assert(power != 0);
 1813     assert(power != 1);
 1814 
 1815     galilean = &unit->galilean;
 1816     tmp = RAISE(galilean->unit, power);
 1817 
 1818     if (tmp != NULL) {
 1819         result = galileanNew(pow(galilean->scale, power), tmp, 0);
 1820 
 1821         ut_free(tmp);
 1822     }
 1823 
 1824     return result;
 1825 }
 1826 
 1827 
 1828 /*
 1829  * Returns the result of taking a root of a Galilean-unit.  Any offset is
 1830  * ignored.
 1831  *
 1832  * Arguments:
 1833  *  unit    The Galilean-unit.
 1834  *  root    The root.  Must be greater than 1 and less than 256.
 1835  * Returns:
 1836  *  NULL    Failure.  "ut_get_status()" will be:
 1837  *          UT_MEANINGLESS  The operation on the given units is
 1838  *                  meaningless.
 1839  *  else    The resulting unit.
 1840  */
 1841 static ut_unit*
 1842 galileanRoot(
 1843     const ut_unit* const    unit,
 1844     const int           root)
 1845 {
 1846     const GalileanUnit*  galilean;
 1847     ut_unit*             tmp;
 1848     ut_unit*             result = NULL;  /* failure */
 1849 
 1850     assert(unit != NULL);
 1851     assert(IS_GALILEAN(unit));
 1852     assert(root > 1 && root <= 255);
 1853 
 1854     galilean = &unit->galilean;
 1855     tmp = ROOT(galilean->unit, root);
 1856 
 1857     if (tmp != NULL) {
 1858         result = galileanNew(pow(galilean->scale, 1.0/root), tmp, 0);
 1859 
 1860         ut_free(tmp);
 1861     }
 1862 
 1863     return result;
 1864 }
 1865 
 1866 
 1867 /*
 1868  * Initializes the converter of numeric values from the given Galilean unit to
 1869  * the underlying product-unit.
 1870  *
 1871  * Arguments:
 1872  *  unit    The Galilean unit.
 1873  * Returns:
 1874  *  -1  Failure.  "ut_get_status()" will be:
 1875  *          UT_OS   Operating-system fault.  See "errno".
 1876  *  0   Success.
 1877  */
 1878 static int
 1879 galileanInitConverterToProduct(
 1880     ut_unit* const  unit)
 1881 {
 1882     int         retCode = -1;   /* failure */
 1883     cv_converter*   toUnderlying;
 1884 
 1885     assert(unit != NULL);
 1886     assert(IS_GALILEAN(unit));
 1887 
 1888     toUnderlying = cv_get_galilean(
 1889     unit->galilean.scale, unit->galilean.offset * unit->galilean.scale);
 1890 
 1891     if (toUnderlying == NULL) {
 1892     ut_set_status(UT_OS);
 1893     ut_handle_error_message(strerror(errno));
 1894     ut_handle_error_message("galileanInitConverterToProduct(): "
 1895         "Couldn't get converter to underlying unit");
 1896     }
 1897     else {
 1898     if (ENSURE_CONVERTER_TO_PRODUCT(unit->galilean.unit)) {
 1899         assert(unit->common.toProduct == NULL);
 1900 
 1901         unit->common.toProduct = cv_combine(
 1902         toUnderlying, unit->galilean.unit->common.toProduct);
 1903 
 1904         if (unit->common.toProduct == NULL) {
 1905         ut_set_status(UT_OS);
 1906         ut_handle_error_message(strerror(errno));
 1907         ut_handle_error_message("galileanInitConverterToProduct(): "
 1908             "Couldn't combine converters");
 1909         }
 1910         else {
 1911         retCode = 0;
 1912         }
 1913     }
 1914 
 1915     cv_free(toUnderlying);
 1916     }               /* "toUnderlying" allocated */
 1917 
 1918     return retCode;
 1919 }
 1920 
 1921 
 1922 /*
 1923  * Initializes the converter of numeric values to the given Galilean unit from
 1924  * the underlying product-unit.
 1925  *
 1926  * Arguments:
 1927  *  unit    The Galilean unit.
 1928  * Returns:
 1929  *  -1  Failure.  "ut_get_status()" will be:
 1930  *          UT_OS   Operating-system fault.  See "errno".
 1931  *  0   Success.
 1932  */
 1933 static int
 1934 galileanInitConverterFromProduct(
 1935     ut_unit* const  unit)
 1936 {
 1937     int         retCode = -1;       /* failure */
 1938     cv_converter*   fromUnderlying;
 1939 
 1940     assert(unit != NULL);
 1941     assert(IS_GALILEAN(unit));
 1942 
 1943     fromUnderlying = cv_get_galilean(
 1944     1.0/unit->galilean.scale, -unit->galilean.offset);
 1945 
 1946     if (fromUnderlying == NULL) {
 1947     ut_set_status(UT_OS);
 1948     ut_handle_error_message(strerror(errno));
 1949     ut_handle_error_message("galileanInitConverterFromProduct(): "
 1950         "Couldn't get converter from underlying unit");
 1951     }
 1952     else {
 1953     if (ENSURE_CONVERTER_FROM_PRODUCT(unit->galilean.unit)) {
 1954         assert(unit->common.fromProduct == NULL);
 1955 
 1956         unit->common.fromProduct = cv_combine(
 1957         unit->galilean.unit->common.fromProduct, fromUnderlying);
 1958 
 1959         if (unit->common.fromProduct == NULL) {
 1960         ut_set_status(UT_OS);
 1961         ut_handle_error_message(strerror(errno));
 1962         ut_handle_error_message("galileanInitConverterFromProduct(): "
 1963             "Couldn't combine converters");
 1964         }
 1965         else {
 1966         retCode = 0;
 1967         }
 1968     }
 1969 
 1970     cv_free(fromUnderlying);
 1971     }               /* "fromUnderlying" allocated */
 1972 
 1973     return retCode;
 1974 }
 1975 
 1976 
 1977 static ut_status
 1978 galileanAcceptVisitor(
 1979     const ut_unit* const        unit,
 1980     const ut_visitor* const visitor,
 1981     void* const         arg)
 1982 {
 1983     assert(unit != NULL);
 1984     assert(IS_GALILEAN(unit));
 1985     assert(visitor != NULL);
 1986 
 1987     return visitor->visit_galilean(unit, unit->galilean.scale,
 1988     unit->galilean.unit, unit->galilean.offset, arg);
 1989 }
 1990 
 1991 
 1992 static UnitOps  galileanOps = {
 1993     galileanGetProduct,
 1994     galileanClone,
 1995     galileanFree,
 1996     galileanCompare,
 1997     galileanMultiply,
 1998     galileanRaise,
 1999     galileanRoot,
 2000     galileanInitConverterToProduct,
 2001     galileanInitConverterFromProduct,
 2002     galileanAcceptVisitor
 2003 };
 2004 
 2005 
 2006 /******************************************************************************
 2007  * Timestamp Unit:
 2008  ******************************************************************************/
 2009 
 2010 
 2011 static UnitOps  timestampOps;
 2012 
 2013 
 2014 /*
 2015  * Returns a new unit instance.
 2016  *
 2017  * Arguments:
 2018  *  unit    The underlying unit.  May be freed upon return.
 2019  *  origin  The timestamp origin.
 2020  * Returns:
 2021  *  NULL    Failure.  "ut_get_status()" will be:
 2022  *          UT_OS       Operating-system error.  See "errno".
 2023  *          UT_MEANINGLESS  Creation of a timestamp unit based on
 2024  *                  "unit" is not meaningful.
 2025  *          UT_NO_SECOND    The associated unit-system doesn't
 2026  *                  contain a second unit.
 2027  *  else    The newly-allocated, timestamp-unit.
 2028  */
 2029 static ut_unit*
 2030 timestampNewOrigin(
 2031     const ut_unit*  unit,
 2032     const double    origin)
 2033 {
 2034     ut_unit*    newUnit = NULL;         /* failure */
 2035     ut_unit*    secondUnit;
 2036 
 2037     assert(unit != NULL);
 2038     assert(!IS_TIMESTAMP(unit));
 2039 
 2040     secondUnit = unit->common.system->second;
 2041 
 2042     if (secondUnit == NULL) {
 2043     ut_set_status(UT_NO_SECOND);
 2044     ut_handle_error_message("galileanInitConverterFromProduct(): "
 2045         "No \"second\" unit defined");
 2046     }
 2047     else if (ut_are_convertible(secondUnit, unit)) {
 2048     TimestampUnit*  timestampUnit = malloc(sizeof(TimestampUnit));
 2049 
 2050     if (timestampUnit == NULL) {
 2051         ut_set_status(UT_OS);
 2052         ut_handle_error_message(strerror(errno));
 2053         ut_handle_error_message("timestampNewOrigin(): "
 2054         "Couldn't allocate %lu-byte timestamp-unit",
 2055         sizeof(TimestampUnit));
 2056     }
 2057     else {
 2058         if (commonInit(&timestampUnit->common, &timestampOps,
 2059             unit->common.system, TIMESTAMP) == 0) {
 2060         timestampUnit->origin = origin;
 2061         timestampUnit->unit = CLONE(unit);
 2062         }
 2063         else {
 2064         free(timestampUnit);
 2065         timestampUnit = NULL;
 2066         }
 2067     }           /* "timestampUnit" allocated */
 2068 
 2069     newUnit = (ut_unit*)timestampUnit;
 2070     }               /* "secondUnit != NULL" && time unit */
 2071 
 2072     return newUnit;
 2073 }
 2074 
 2075 
 2076 #if 0
 2077 /*
 2078  * Returns a new unit instance.
 2079  *
 2080  * Arguments:
 2081  *  unit    The underlying unit.  May be freed upon return.
 2082  *  year    The year of the origin.
 2083  *  month   The month of the origin.
 2084  *  day The day of the origin.
 2085  *  hour    The hour of the origin.
 2086  *  minute  The minute of the origin.
 2087  *  second  The second of the origin.
 2088  * Returns:
 2089  *  NULL    Failure.  "ut_get_status()" will be:
 2090  *          UT_OS       Operating-system error.  See "errno".
 2091  *          UT_MEANINGLESS  Creation of a timestamp unit base on
 2092  *                  "unit" is not meaningful.
 2093  *          UT_NO_SECOND    The associated unit-system doesn't
 2094  *                  contain a unit named "second".
 2095  *  else    The newly-allocated, timestamp-unit.
 2096  */
 2097 static ut_unit*
 2098 timestampNew(
 2099     ut_unit*    unit,
 2100     const int   year,
 2101     const int   month,
 2102     const int   day,
 2103     const int   hour,
 2104     const int   minute,
 2105     double  second)
 2106 {
 2107     assert(unit != NULL);
 2108 
 2109     return timestampNewOrigin(
 2110     unit, ut_encode_time(year, month, day, hour, minute, second));
 2111 }
 2112 #endif
 2113 
 2114 
 2115 static ProductUnit*
 2116 timestampGetProduct(
 2117     const ut_unit* const    unit)
 2118 {
 2119     assert(unit != NULL);
 2120     assert(IS_TIMESTAMP(unit));
 2121 
 2122     return GET_PRODUCT(unit->timestamp.unit);
 2123 }
 2124 
 2125 
 2126 static ut_unit*
 2127 timestampClone(
 2128     const ut_unit* const    unit)
 2129 {
 2130     assert(unit != NULL);
 2131     assert(IS_TIMESTAMP(unit));
 2132 
 2133     return timestampNewOrigin(unit->timestamp.unit, unit->timestamp.origin);
 2134 }
 2135 
 2136 
 2137 static int
 2138 timestampCompare(
 2139     const ut_unit* const    unit1,
 2140     const ut_unit* const    unit2)
 2141 {
 2142     int cmp;
 2143 
 2144     assert(unit1 != NULL);
 2145     assert(IS_TIMESTAMP(unit1));
 2146     assert(unit2 != NULL);
 2147 
 2148     if (!IS_TIMESTAMP(unit2)) {
 2149     int diff = unit1->common.type - unit2->common.type;
 2150 
 2151     cmp = diff < 0 ? -1 : diff == 0 ? 0 : 1;
 2152     }
 2153     else {
 2154     const TimestampUnit* const  timestamp1 = &unit1->timestamp;
 2155     const TimestampUnit* const  timestamp2 = &unit2->timestamp;
 2156 
 2157     cmp =
 2158         timestamp1->origin < timestamp2->origin
 2159         ? -1
 2160         : timestamp1->origin == timestamp2->origin
 2161             ? 0
 2162             : -1;
 2163 
 2164     if (cmp == 0)
 2165         cmp = COMPARE(timestamp1->unit, timestamp2->unit);
 2166     }
 2167 
 2168     return cmp;
 2169 }
 2170 
 2171 
 2172 static void
 2173 timestampFree(
 2174     ut_unit* const  unit)
 2175 {
 2176     if (unit != NULL) {
 2177     assert(IS_TIMESTAMP(unit));
 2178     FREE(unit->timestamp.unit);
 2179     unit->timestamp.unit = NULL;
 2180     cv_free(unit->common.toProduct);
 2181     unit->common.toProduct = NULL;
 2182     cv_free(unit->common.fromProduct);
 2183     unit->common.fromProduct = NULL;
 2184     free((void*)unit);
 2185     }
 2186 }
 2187 
 2188 
 2189 /*
 2190  * Multiplies a timestamp-unit by another unit.  The origin is ignored.
 2191  *
 2192  * Arguments:
 2193  *  unit1   The timestamp-unit.
 2194  *  unit2   The other unit.
 2195  * Returns:
 2196  *  NULL    Failure.  "ut_get_status()" will be:
 2197  *          UT_MEANINGLESS  The operation on the given units is
 2198  *                  meaningless.
 2199  *  else    The resulting unit.
 2200  */
 2201 static ut_unit*
 2202 timestampMultiply(
 2203     const ut_unit* const    unit1,
 2204     const ut_unit* const    unit2)
 2205 {
 2206     assert(unit1 != NULL);
 2207     assert(IS_TIMESTAMP(unit1));
 2208     assert(unit2 != NULL);
 2209 
 2210     return MULTIPLY(unit1->timestamp.unit, unit2);
 2211 }
 2212 
 2213 
 2214 /*
 2215  * Returns the result of raising a Timestamp-unit to a power.  The origin is
 2216  * ignored.
 2217  *
 2218  * Arguments:
 2219  *  unit    The Timestamp-unit.
 2220  *  power   The power.  Must be greater than -256 and less than 256.
 2221  * Returns:
 2222  *  NULL    Failure.  "ut_get_status()" will be:
 2223  *          UT_MEANINGLESS  The operation on the given units is
 2224  *                  meaningless.
 2225  *  else    The resulting unit.
 2226  */
 2227 static ut_unit*
 2228 timestampRaise(
 2229     const ut_unit* const    unit,
 2230     const int           power)
 2231 {
 2232     assert(unit != NULL);
 2233     assert(IS_TIMESTAMP(unit));
 2234     assert(power != 0);
 2235     assert(power != 1);
 2236 
 2237     return RAISE(unit->timestamp.unit, power);
 2238 }
 2239 
 2240 
 2241 /*
 2242  * Returns the result of taking a root of a Timestamp-unit.  The origin is
 2243  * ignored.
 2244  *
 2245  * Arguments:
 2246  *  unit    The Timestamp-unit.
 2247  *  root    The root.  Must be greater than 1 and less than 256.
 2248  * Returns:
 2249  *  NULL    Failure.  "ut_get_status()" will be:
 2250  *          UT_MEANINGLESS  The operation on the given units is
 2251  *                  meaningless.
 2252  *  else    The resulting unit.
 2253  */
 2254 static ut_unit*
 2255 timestampRoot(
 2256     const ut_unit* const    unit,
 2257     const int           root)
 2258 {
 2259     assert(unit != NULL);
 2260     assert(IS_TIMESTAMP(unit));
 2261     assert(root > 1 && root < 256);
 2262 
 2263     return ROOT(unit->timestamp.unit, root);
 2264 }
 2265 
 2266 
 2267 /*
 2268  * Initializes the converter of numeric values from the given Timestamp unit to
 2269  * the underlying product-unit.
 2270  *
 2271  * Arguments:
 2272  *  unit    The Timestamp unit.
 2273  * Returns:
 2274  *  -1  Failure.
 2275  */
 2276 static int
 2277 timestampInitConverterToProduct(
 2278     ut_unit* const  unit)
 2279 {
 2280     /*
 2281      * This function is never called.
 2282      */
 2283     assert(0);
 2284 
 2285     return -1;
 2286 }
 2287 
 2288 
 2289 /*
 2290  * Initializes the converter of numeric values to the given Timestamp unit from
 2291  * the underlying product-unit.
 2292  *
 2293  * Arguments:
 2294  *  unit    The Timestamp unit.
 2295  * Returns:
 2296  *  -1  Failure.
 2297  */
 2298 static int
 2299 timestampInitConverterFromProduct(
 2300     ut_unit* const  unit)
 2301 {
 2302     /*
 2303      * This function is never called.
 2304      */
 2305     assert(0);
 2306 
 2307     return -1;
 2308 }
 2309 
 2310 
 2311 static ut_status
 2312 timestampAcceptVisitor(
 2313     const ut_unit* const        unit,
 2314     const ut_visitor* const visitor,
 2315     void* const         arg)
 2316 {
 2317     assert(unit != NULL);
 2318     assert(IS_TIMESTAMP(unit));
 2319     assert(visitor != NULL);
 2320 
 2321     return visitor->visit_timestamp(unit, unit->timestamp.unit,
 2322         unit->timestamp.origin, arg);
 2323 }
 2324 
 2325 
 2326 static UnitOps  timestampOps = {
 2327     timestampGetProduct,
 2328     timestampClone,
 2329     timestampFree,
 2330     timestampCompare,
 2331     timestampMultiply,
 2332     timestampRaise,
 2333     timestampRoot,
 2334     timestampInitConverterToProduct,
 2335     timestampInitConverterFromProduct,
 2336     timestampAcceptVisitor
 2337 };
 2338 
 2339 
 2340 /******************************************************************************
 2341  * Logarithmic Unit:
 2342  ******************************************************************************/
 2343 
 2344 
 2345 static UnitOps  logOps;
 2346 
 2347 
 2348 /*
 2349  * Returns a new instance.
 2350  *
 2351  * Arguments:
 2352  *  base        The logarithmic base (e.g., 2, M_E, 10).  Must be
 2353  *                      greater than one.
 2354  *  reference   The reference value.
 2355  * Returns:
 2356  *  NULL    Failure.  "ut_get_status()" will be:
 2357  *          UT_OS   Operating-system error.  See "errno".
 2358  *  else    The newly-allocated, logarithmic-unit.
 2359  */
 2360 static ut_unit*
 2361 logNew(
 2362     const double        base,
 2363     const ut_unit* const    reference)
 2364 {
 2365     LogUnit*    logUnit;
 2366 
 2367     assert(base > 1);
 2368     assert(reference != NULL);
 2369 
 2370     logUnit = malloc(sizeof(LogUnit));
 2371 
 2372     if (logUnit == NULL) {
 2373     ut_set_status(UT_OS);
 2374     ut_handle_error_message(strerror(errno));
 2375     ut_handle_error_message(
 2376         "logNew(): Couldn't allocate %lu-byte logarithmic-unit",
 2377         sizeof(LogUnit));
 2378     }
 2379     else {
 2380     if (commonInit(&logUnit->common, &logOps, reference->common.system,
 2381         LOG) != 0) {
 2382         free(logUnit);
 2383     }
 2384     else {
 2385         logUnit->reference = CLONE(reference);
 2386 
 2387         if (logUnit->reference != NULL) {
 2388         logUnit->base = base;
 2389         }
 2390         else {
 2391         free(logUnit);
 2392         logUnit = NULL;
 2393         }
 2394     }
 2395     }
 2396 
 2397     return (ut_unit*)logUnit;
 2398 }
 2399 
 2400 
 2401 static ProductUnit*
 2402 logGetProduct(
 2403     const ut_unit* const    unit)
 2404 {
 2405     assert(unit != NULL);
 2406     assert(IS_LOG(unit));
 2407 
 2408     return GET_PRODUCT(unit->log.reference);
 2409 }
 2410 
 2411 
 2412 static ut_unit*
 2413 logClone(
 2414     const ut_unit* const    unit)
 2415 {
 2416     assert(unit != NULL);
 2417     assert(IS_LOG(unit));
 2418 
 2419     return logNew(unit->log.base, unit->log.reference);
 2420 }
 2421 
 2422 
 2423 static int
 2424 logCompare(
 2425     const ut_unit* const    unit1,
 2426     const ut_unit* const    unit2)
 2427 {
 2428     int cmp;
 2429 
 2430     assert(unit1 != NULL);
 2431     assert(IS_LOG(unit1));
 2432     assert(unit2 != NULL);
 2433 
 2434     if (!IS_LOG(unit2)) {
 2435     int diff = unit1->common.type - unit2->common.type;
 2436 
 2437     cmp = diff < 0 ? -1 : diff == 0 ? 0 : 1;
 2438     }
 2439     else {
 2440     const LogUnit* const    u1 = &unit1->log;
 2441     const LogUnit* const    u2 = &unit2->log;
 2442 
 2443     cmp = ut_compare(u1->reference, u2->reference);
 2444 
 2445     if (cmp == 0)
 2446         cmp =
 2447         u1->base < u2->base
 2448             ? -1
 2449             : u1->base == u2->base
 2450             ? 0
 2451             : 1;
 2452     }
 2453 
 2454     return cmp;
 2455 }
 2456 
 2457 
 2458 static void
 2459 logFree(
 2460     ut_unit* const  unit)
 2461 {
 2462     if (unit != NULL) {
 2463     assert(IS_LOG(unit));
 2464     FREE(unit->log.reference);
 2465     unit->log.reference = NULL;
 2466     cv_free(unit->common.toProduct);
 2467     unit->common.toProduct = NULL;
 2468     cv_free(unit->common.fromProduct);
 2469     unit->common.fromProduct = NULL;
 2470     free((void*)unit);
 2471     }
 2472 }
 2473 
 2474 
 2475 /*
 2476  * Multiplies a logarithmic-unit by another unit.
 2477  *
 2478  * Arguments:
 2479  *  unit1   The logarithmic-unit.
 2480  *  unit2   The other unit.
 2481  * Returns:
 2482  *  NULL    Failure.  "ut_get_status()" will be:
 2483  *          UT_MEANINGLESS  The operation on the given units is
 2484  *                  meaningless.
 2485  *  else    The resulting unit.
 2486  */
 2487 static ut_unit*
 2488 logMultiply(
 2489     const ut_unit* const    unit1,
 2490     const ut_unit* const    unit2)
 2491 {
 2492     ut_unit*    result = NULL;      /* failure */
 2493 
 2494     assert(unit1 != NULL);
 2495     assert(IS_LOG(unit1));
 2496     assert(unit2 != NULL);
 2497 
 2498     if (!ut_is_dimensionless(unit2)) {
 2499     ut_set_status(UT_MEANINGLESS);
 2500     ut_handle_error_message("logMultiply(): Second unit not dimensionless");
 2501     }
 2502     else if (IS_BASIC(unit2) || IS_PRODUCT(unit2)) {
 2503     result = CLONE(unit1);
 2504     }
 2505     else if (IS_GALILEAN(unit2)) {
 2506     result = galileanNew(unit2->galilean.scale, unit1, 0);
 2507     }
 2508     else {
 2509     ut_set_status(UT_MEANINGLESS);
 2510     ut_handle_error_message("logMultiply(): can't multiply second unit");
 2511     }
 2512 
 2513     return result;
 2514 }
 2515 
 2516 
 2517 /*
 2518  * Returns the result of raising a logarithmic-unit to a power.
 2519  *
 2520  * Arguments:
 2521  *  unit    The logarithmic-unit.
 2522  *  power   The power.  Must be greater than -256 and less than 256.
 2523  * Returns:
 2524  *  NULL    Failure.  "ut_get_status()" will be:
 2525  *          UT_MEANINGLESS  The operation on the given units is
 2526  *                  meaningless.
 2527  *  else    The resulting unit.
 2528  */
 2529 static ut_unit*
 2530 logRaise(
 2531     const ut_unit* const    unit,
 2532     const int           power)
 2533 {
 2534     assert(unit != NULL);
 2535     assert(IS_LOG(unit));
 2536     assert(power != 0);
 2537     assert(power != 1);
 2538 
 2539     /*
 2540      * We don't know how to raise a logarithmic unit to a non-zero power.
 2541      */
 2542     ut_set_status(UT_MEANINGLESS);
 2543     ut_handle_error_message(
 2544     "logRaise(): Can't raise logarithmic-unit to non-zero power");
 2545 
 2546     return NULL;
 2547 }
 2548 
 2549 
 2550 /*
 2551  * Returns the result of taking a root of a logarithmic-unit.
 2552  *
 2553  * Arguments:
 2554  *  unit    The logarithmic-unit.
 2555  *  root    The root.  Must be greater than 1 and less than 256.
 2556  * Returns:
 2557  *  NULL    Failure.  "ut_get_status()" will be:
 2558  *          UT_MEANINGLESS  The operation on the given units is
 2559  *                  meaningless.
 2560  *  else    The resulting unit.
 2561  */
 2562 static ut_unit*
 2563 logRoot(
 2564     const ut_unit* const    unit,
 2565     const int           root)
 2566 {
 2567     assert(unit != NULL);
 2568     assert(IS_LOG(unit));
 2569     assert(root > 1 && root < 256);
 2570 
 2571     /*
 2572      * We don't know how to take a root of a logarithmic unit.
 2573      */
 2574     ut_set_status(UT_MEANINGLESS);
 2575     ut_handle_error_message(
 2576     "logRoot(): Can't take a non-unity root of a logarithmic-unit");
 2577 
 2578     return NULL;
 2579 }
 2580 
 2581 
 2582 /*
 2583  * Initializes the converter of numeric values from the given logarithmic unit
 2584  * to the underlying product-unit.
 2585  *
 2586  * Arguments:
 2587  *  unit    The logarithmic unit.
 2588  * Returns:
 2589  *  -1  Failure.  "ut_get_status()" will be:
 2590  *          UT_OS   Operating-system fault.  See "errno".
 2591  *  0   Success.
 2592  */
 2593 static int
 2594 logInitConverterToProduct(
 2595     ut_unit* const  unit)
 2596 {
 2597     int         retCode = -1;       /* failure */
 2598     cv_converter*   toUnderlying;
 2599 
 2600     assert(unit != NULL);
 2601     assert(IS_LOG(unit));
 2602 
 2603     toUnderlying = cv_get_pow(unit->log.base);
 2604 
 2605     if (toUnderlying == NULL) {
 2606     ut_set_status(UT_OS);
 2607     ut_handle_error_message(strerror(errno));
 2608     ut_handle_error_message("logInitConverterToProduct(): "
 2609         "Couldn't get converter to underlying unit");
 2610     }
 2611     else {
 2612     if (ENSURE_CONVERTER_TO_PRODUCT(unit->log.reference)) {
 2613         assert(unit->common.toProduct == NULL);
 2614 
 2615         unit->common.toProduct = cv_combine(
 2616         toUnderlying, unit->log.reference->common.toProduct);
 2617 
 2618         if (unit->common.toProduct == NULL) {
 2619         ut_set_status(UT_OS);
 2620         ut_handle_error_message(strerror(errno));
 2621         ut_handle_error_message("logInitConverterToProduct(): "
 2622             "Couldn't combine converters");
 2623         }
 2624         else {
 2625         retCode = 0;
 2626         }
 2627     }
 2628 
 2629     cv_free(toUnderlying);
 2630     }               /* "toUnderlying" allocated */
 2631 
 2632     return retCode;
 2633 }
 2634 
 2635 
 2636 /*
 2637  * Initializes the converter of numeric values to the given logarithmic unit
 2638  * from the underlying product-unit.
 2639  *
 2640  * Arguments:
 2641  *  unit    The logarithmic unit.
 2642  * Returns:
 2643  *  -1  Failure.  "ut_get_status()" will be:
 2644  *          UT_OS       Operating-system fault.  See "errno".
 2645  *  0   Success.
 2646  */
 2647 static int
 2648 logInitConverterFromProduct(
 2649     ut_unit* const  unit)
 2650 {
 2651     int         retCode = -1;       /* failure */
 2652     cv_converter*   fromUnderlying;
 2653 
 2654     assert(unit != NULL);
 2655     assert(IS_LOG(unit));
 2656 
 2657     fromUnderlying = cv_get_log(unit->log.base);
 2658 
 2659     if (fromUnderlying == NULL) {
 2660     ut_set_status(UT_OS);
 2661     ut_handle_error_message(strerror(errno));
 2662     ut_handle_error_message("logInitConverterFromProduct(): "
 2663         "Couldn't get converter from underlying unit");
 2664     }
 2665     else {
 2666     if (ENSURE_CONVERTER_FROM_PRODUCT(unit->log.reference)) {
 2667         assert(unit->common.fromProduct == NULL);
 2668 
 2669         unit->common.fromProduct = cv_combine(
 2670         unit->log.reference->common.fromProduct, fromUnderlying);
 2671 
 2672         if (unit->common.fromProduct == NULL) {
 2673         ut_set_status(UT_OS);
 2674         ut_handle_error_message(strerror(errno));
 2675         ut_handle_error_message("logInitConverterFromProduct(): "
 2676             "Couldn't combine converters");
 2677         }
 2678         else {
 2679         retCode = 0;
 2680         }
 2681     }
 2682 
 2683     cv_free(fromUnderlying);
 2684     }               /* "fromUnderlying" allocated */
 2685 
 2686     return retCode;
 2687 }
 2688 
 2689 
 2690 static ut_status
 2691 logAcceptVisitor(
 2692     const ut_unit* const        unit,
 2693     const ut_visitor* const visitor,
 2694     void* const         arg)
 2695 {
 2696     assert(unit != NULL);
 2697     assert(IS_LOG(unit));
 2698     assert(visitor != NULL);
 2699 
 2700     return visitor->visit_logarithmic(unit, unit->log.base, unit->log.reference,
 2701     arg);
 2702 }
 2703 
 2704 
 2705 static UnitOps  logOps = {
 2706     logGetProduct,
 2707     logClone,
 2708     logFree,
 2709     logCompare,
 2710     logMultiply,
 2711     logRaise,
 2712     logRoot,
 2713     logInitConverterToProduct,
 2714     logInitConverterFromProduct,
 2715     logAcceptVisitor
 2716 };
 2717 
 2718 
 2719 /******************************************************************************
 2720  * Public API:
 2721  ******************************************************************************/
 2722 
 2723 
 2724 /*
 2725  * Returns a new unit-system.  On success, the unit-system will only contain
 2726  * the dimensionless unit one.  See "ut_get_dimensionless_unit_one()".
 2727  *
 2728  * Returns:
 2729  *  NULL    Failure.  "ut_get_status()" will be:
 2730  *          UT_OS   Operating-system error.  See "errno".
 2731  *  else    Pointer to a new unit system.
 2732  */
 2733 ut_system*
 2734 ut_new_system(void)
 2735 {
 2736     ut_system*  system = malloc(sizeof(ut_system));
 2737 
 2738     ut_set_status(UT_SUCCESS);
 2739 
 2740     if (system == NULL) {
 2741     ut_set_status(UT_OS);
 2742     ut_handle_error_message(strerror(errno));
 2743     ut_handle_error_message(
 2744         "ut_new_system(): Couldn't allocate %lu-byte unit-system",
 2745         sizeof(ut_system));
 2746     }
 2747     else {
 2748     system->second = NULL;
 2749     system->basicUnits = NULL;
 2750     system->basicCount = 0;
 2751 
 2752     system->one = (ut_unit*)productNew(system, NULL, NULL, 0);
 2753 
 2754     if (ut_get_status() != UT_SUCCESS) {
 2755         ut_handle_error_message(
 2756         "ut_new_system(): Couldn't create dimensionless unit one");
 2757         free(system);
 2758             system = NULL;
 2759     }
 2760     }
 2761 
 2762     return system;
 2763 }
 2764 
 2765 
 2766 /*
 2767  * Frees resources associated with a unit-system by this module.
 2768  *
 2769  * Arguments:
 2770  *  system      Pointer to the unit-system.
 2771  */
 2772 void
 2773 coreFreeSystem(
 2774     ut_system*  system)
 2775 {
 2776     if (system != NULL) {
 2777     int i;
 2778 
 2779     for (i = 0; i < system->basicCount; ++i)
 2780         basicFree((ut_unit*)system->basicUnits[i]);
 2781 
 2782     free(system->basicUnits);
 2783 
 2784     if (system->second != NULL)
 2785         FREE(system->second);
 2786 
 2787     if (system->one != NULL)
 2788         productReallyFree(system->one);
 2789 
 2790     free(system);
 2791     }
 2792 }
 2793 
 2794 
 2795 /*
 2796  * Returns the dimensionless-unit one of a unit-system.
 2797  *
 2798  * Arguments:
 2799  *  system  Pointer to the unit-system for which the dimensionless-unit one
 2800  *      will be returned.
 2801  * Returns:
 2802  *  NULL    Failure.  "utgetStatus()" will be:
 2803  *          UT_BAD_ARG  "system" is NULL.
 2804  *  else    Pointer to the dimensionless-unit one associated with "system".
 2805  *      While not necessary, the pointer may be passed to ut_free()
 2806  *      when the unit is no longer needed by the client.
 2807  */
 2808 ut_unit*
 2809 ut_get_dimensionless_unit_one(
 2810     const ut_system* const  system)
 2811 {
 2812     ut_unit*    one;
 2813 
 2814     ut_set_status(UT_SUCCESS);
 2815 
 2816     if (system == NULL) {
 2817     one = NULL;
 2818     ut_set_status(UT_BAD_ARG);
 2819     ut_handle_error_message(
 2820         "ut_get_dimensionless_unit_one(): NULL unit-system argument");
 2821     }
 2822     else {
 2823     one = system->one;
 2824     }
 2825 
 2826     return one;
 2827 }
 2828 
 2829 
 2830 /*
 2831  * Returns the unit-system to which a unit belongs.
 2832  *
 2833  * Arguments:
 2834  *  unit    Pointer to the unit in question.
 2835  * Returns:
 2836  *  NULL    Failure.  "ut_get_status()" will be
 2837  *          UT_BAD_ARG  "unit" is NULL.
 2838  *  else    Pointer to the unit-system to which "unit" belongs.
 2839  */
 2840 ut_system*
 2841 ut_get_system(
 2842     const ut_unit* const    unit)
 2843 {
 2844     ut_system*  system;
 2845 
 2846     ut_set_status(UT_SUCCESS);
 2847 
 2848     if (unit == NULL) {
 2849     system = NULL;
 2850     ut_set_status(UT_BAD_ARG);
 2851     ut_handle_error_message("ut_get_system(): NULL unit argument");
 2852     }
 2853     else {
 2854     system = unit->common.system;
 2855     }
 2856 
 2857     return system;
 2858 }
 2859 
 2860 
 2861 /*
 2862  * Indicates if two units belong to the same unit-system.
 2863  *
 2864  * Arguments:
 2865  *  unit1       Pointer to a unit.
 2866  *  unit2       Pointer to another unit.
 2867  * Returns:
 2868  *  0       Failure or the units belong to different unit-systems.
 2869  *          "ut_get_status()" will be
 2870  *                  UT_BAD_ARG      "unit1" or "unit2" is NULL.
 2871  *                  UT_SUCCESS      The units belong to different
 2872  *                      unit-systems.
 2873  *  else        The units belong to the same unit-system.
 2874  */
 2875 int
 2876 ut_same_system(
 2877     const ut_unit* const    unit1,
 2878     const ut_unit* const    unit2)
 2879 {
 2880     int sameSystem = 0;
 2881 
 2882     if (unit1 == NULL || unit2 == NULL) {
 2883     ut_set_status(UT_BAD_ARG);
 2884     ut_handle_error_message("ut_same_system(): NULL argument");
 2885     }
 2886     else {
 2887     ut_set_status(UT_SUCCESS);
 2888     sameSystem = unit1->common.system == unit2->common.system;
 2889     }
 2890 
 2891     return sameSystem;
 2892 }
 2893 
 2894 
 2895 /*
 2896  * Returns a new basic-unit that has been added to a unit-system.
 2897  *
 2898  * Arguments:
 2899  *  system      The unit-system to which to add the new basic-unit.
 2900  *  isDimensionless Whether or not the basic-unit is dimensionless (e.g.,
 2901  *          a radian).
 2902  * Returns:
 2903  *  NULL    Failure.  "ut_get_status()" will be
 2904  *          UT_BAD_ARG      "system" is NULL.
 2905  *          UT_OS       Operating-system error.  See "errno".
 2906  *  else    Pointer to the new base-unit.
 2907  */
 2908 static BasicUnit*
 2909 newBasicUnit(
 2910     ut_system* const    system,
 2911     const int       isDimensionless)
 2912 {
 2913     BasicUnit*  basicUnit = NULL;   /* failure */
 2914 
 2915     if (system == NULL) {
 2916     ut_set_status(UT_BAD_ARG);
 2917     ut_handle_error_message("newBasicUnit(): NULL unit-system argument");
 2918     }
 2919     else {
 2920     basicUnit = basicNew(system, isDimensionless, system->basicCount);
 2921 
 2922     if (basicUnit != NULL) {
 2923         int     error = 1;
 2924         BasicUnit*  save = (BasicUnit*)basicClone((ut_unit*)basicUnit);
 2925 
 2926         if (save == NULL) {
 2927         ut_set_status(UT_OS);
 2928         ut_handle_error_message(strerror(errno));
 2929         ut_handle_error_message(
 2930             "newBasicUnit(): Couldn't clone basic-unit");
 2931         }
 2932         else {
 2933         BasicUnit** basicUnits = realloc(system->basicUnits,
 2934             (system->basicCount+1)*sizeof(BasicUnit*));
 2935 
 2936         if (basicUnits == NULL) {
 2937             ut_set_status(UT_OS);
 2938             ut_handle_error_message(strerror(errno));
 2939             ut_handle_error_message("newBasicUnit(): "
 2940             "Couldn't allocate %d-element basic-unit array",
 2941             system->basicCount+1);
 2942         }
 2943         else {
 2944             basicUnits[system->basicCount++] = save;
 2945             system->basicUnits = basicUnits;
 2946             error = 0;
 2947         }           /* "system->basicUnits" re-allocated */
 2948 
 2949         if (error)
 2950             basicFree((ut_unit*)save);
 2951         }               /* "save" allocated */
 2952 
 2953         if (error) {
 2954         basicFree((ut_unit*)basicUnit);
 2955         basicUnit = NULL;
 2956         }
 2957     }               /* "basicUnit" allocated */
 2958     }                   /* valid arguments */
 2959 
 2960     return basicUnit;
 2961 }
 2962 
 2963 
 2964 /*
 2965  * Adds a base-unit to a unit-system.  Clients that use ut_read_xml() should not
 2966  * normally need to call this function.
 2967  *
 2968  * Arguments:
 2969  *  system  Pointer to the unit-system to which to add the new base-unit.
 2970  * Returns:
 2971  *  NULL    Failure.  "ut_get_status()" will be
 2972  *          UT_BAD_ARG      "system" or "name" is NULL.
 2973  *          UT_OS       Operating-system error.  See "errno".
 2974  *  else    Pointer to the new base-unit.  The pointer should be passed to
 2975  *      ut_free() when the unit is no longer needed by the client (the
 2976  *      unit will remain in the unit-system).
 2977  */
 2978 ut_unit*
 2979 ut_new_base_unit(
 2980     ut_system* const    system)
 2981 {
 2982     BasicUnit*  basicUnit = newBasicUnit(system, 0);
 2983 
 2984     return (ut_unit*)basicUnit;
 2985 }
 2986 
 2987 
 2988 /*
 2989  * Adds a dimensionless-unit to a unit-system.  In the SI system of units, the
 2990  * derived-unit radian is a dimensionless-unit.  Clients that use ut_read_xml()
 2991  * should not normally need to call this function.
 2992  *
 2993  * Arguments:
 2994  *  system  Pointer to the unit-system to which to add the new
 2995  *      dimensionless-unit.
 2996  * Returns:
 2997  *  NULL    Failure.  "ut_get_status()" will be
 2998  *          UT_BAD_ARG      "system" is NULL.
 2999  *          UT_OS       Operating-system error.  See "errno".
 3000  *  else    Pointer to the new dimensionless-unit.  The pointer should be
 3001  *      passed to ut_free() when the unit is no longer needed by the
 3002  *      client (the unit will remain in the unit-system).
 3003  */
 3004 ut_unit*
 3005 ut_new_dimensionless_unit(
 3006     ut_system* const    system)
 3007 {
 3008     return (ut_unit*)newBasicUnit(system, 1);
 3009 }
 3010 
 3011 
 3012 /*
 3013  * Sets the "second" unit of a unit-system.  This function must be called before
 3014  * the first call to "ut_offset_by_time()". ut_read_xml() calls this function if the
 3015  * resulting unit-system contains a unit named "second".
 3016  *
 3017  * Arguments:
 3018  *  second      Pointer to the "second" unit.
 3019  * Returns:
 3020  *  UT_BAD_ARG  "second" is NULL.
 3021  *  UT_EXISTS   The second unit of the unit-system to which "second"
 3022  *          belongs is set to a different unit.
 3023  *  UT_SUCCESS  Success.
 3024  */
 3025 ut_status
 3026 ut_set_second(
 3027     const ut_unit* const    second)
 3028 {
 3029     ut_set_status(UT_SUCCESS);
 3030 
 3031     if (second == NULL) {
 3032     ut_set_status(UT_BAD_ARG);
 3033     ut_handle_error_message(
 3034             "ut_set_second(): NULL \"second\" unit argument");
 3035     }
 3036     else {
 3037     ut_system*  system = second->common.system;
 3038 
 3039     if (system->second == NULL) {
 3040         system->second = CLONE(second);
 3041     }
 3042     else {
 3043         if (ut_compare(system->second, second) != 0) {
 3044         ut_set_status(UT_EXISTS);
 3045         ut_handle_error_message(
 3046             "ut_set_second(): Different \"second\" unit already "
 3047                     "defined");
 3048         }
 3049     }
 3050     }
 3051 
 3052     return ut_get_status();
 3053 }
 3054 
 3055 
 3056 /*
 3057  * Compares two units.  Returns a value less than, equal to, or greater than
 3058  * zero as the first unit is considered less than, equal to, or greater than
 3059  * the second unit, respectively.  Units from different unit-systems never
 3060  * compare equal.
 3061  *
 3062  * Arguments:
 3063  *  unit1       Pointer to a unit or NULL.
 3064  *  unit2       Pointer to another unit or NULL.
 3065  * Returns:
 3066  *  <0  The first unit is less than the second unit.
 3067  *   0  The first and second units are equal or both units are NULL.
 3068  *  >0  The first unit is greater than the second unit.
 3069  */
 3070 int
 3071 ut_compare(
 3072     const ut_unit* const    unit1,
 3073     const ut_unit* const    unit2)
 3074 {
 3075     int cmp = 0;
 3076 
 3077     ut_set_status(UT_SUCCESS);
 3078 
 3079     if (unit1 == NULL) {
 3080     cmp = unit2 != NULL ? -1 : 0;
 3081     }
 3082     else if (unit2 == NULL) {
 3083     cmp = 1;
 3084     }
 3085     else if (unit1->common.system < unit2->common.system) {
 3086     cmp = -1;
 3087     }
 3088     else if (unit1->common.system > unit2->common.system) {
 3089     cmp = 1;
 3090     }
 3091     else {
 3092     /*
 3093      * NB: The comparison function is called if and only if the units
 3094      * belong to the same unit-system.
 3095      */
 3096     cmp = COMPARE(unit1, unit2);
 3097     }
 3098 
 3099     return cmp;
 3100 }
 3101 
 3102 
 3103 /*
 3104  * Returns a unit equivalent to another unit scaled by a numeric factor,
 3105  * e.g.,
 3106  *  const ut_unit*  meter = ...
 3107  *  const ut_unit*  kilometer = ut_scale(1000, meter);
 3108  *
 3109  * Arguments:
 3110  *  factor      The numeric scale factor.
 3111  *  unit        Pointer to the unit to be scaled.
 3112  * Returns:
 3113  *  NULL        Failure.  "ut_get_status()" will be
 3114  *              UT_BAD_ARG      "factor" is 0 or "unit" is NULL.
 3115  *              UT_OS       Operating-system error.  See
 3116  *                      "errno".
 3117  *  else        Pointer to the resulting unit.  The pointer should be
 3118  *          passed to ut_free() when the unit is no longer needed by
 3119  *          the client.
 3120  */
 3121 ut_unit*
 3122 ut_scale(
 3123     const double        factor,
 3124     const ut_unit* const    unit)
 3125 {
 3126     ut_unit*        result = NULL;  /* failure */
 3127 
 3128     ut_set_status(UT_SUCCESS);
 3129 
 3130     if (unit == NULL) {
 3131     ut_set_status(UT_BAD_ARG);
 3132     ut_handle_error_message("ut_scale(): NULL unit argument");
 3133     }
 3134     else {
 3135     if (factor == 0) {
 3136         ut_set_status(UT_BAD_ARG);
 3137         ut_handle_error_message("ut_scale(): NULL factor argument");
 3138     }
 3139     else {
 3140         result = factor == 1
 3141         ? CLONE(unit)
 3142         : galileanNew(factor, unit, 0.0);
 3143     }
 3144     }
 3145 
 3146     return result;
 3147 }
 3148 
 3149 
 3150 /*
 3151  * Returns a unit equivalent to another unit offset by a numeric amount,
 3152  * e.g.,
 3153  *  const ut_unit*  kelvin = ...
 3154  *  const ut_unit*  celsius = ut_offset(kelvin, 273.15);
 3155  *
 3156  * Arguments:
 3157  *  unit        Pointer to the unit to be offset.
 3158  *  offset      The numeric offset.
 3159  * Returns:
 3160  *  NULL        Failure.  "ut_get_status()" will be
 3161  *              UT_BAD_ARG      "unit" is NULL.
 3162  *              UT_OS       Operating-system error.  See
 3163  *                      "errno".
 3164  *  else        Pointer to the resulting unit.  The pointer should be
 3165  *          passed to ut_free() when the unit is no longer needed by
 3166  *          the client.
 3167  */
 3168 ut_unit*
 3169 ut_offset(
 3170     const ut_unit* const    unit,
 3171     const double        offset)
 3172 {
 3173     ut_unit*        result = NULL;  /* failure */
 3174 
 3175     ut_set_status(UT_SUCCESS);
 3176 
 3177     if (unit == NULL) {
 3178     ut_set_status(UT_BAD_ARG);
 3179     ut_handle_error_message("ut_offset(): NULL unit argument");
 3180     }
 3181     else {
 3182     result = offset == 0
 3183         ? CLONE(unit)
 3184         : galileanNew(1.0, unit, offset);
 3185     }
 3186 
 3187     return result;
 3188 }
 3189 
 3190 
 3191 /*
 3192  * Returns a unit equivalent to another unit relative to a particular time.
 3193  * e.g.,
 3194  *  const ut_unit*  second = ...
 3195  *  const ut_unit*  secondsSinceTheEpoch =
 3196  *              ut_offset_by_time(second, ut_encode_time(1970, 1, 1, 0, 0, 0.0));
 3197  *
 3198  * Arguments:
 3199  *  unit    Pointer to the time-unit to be made relative to a time-origin.
 3200  *  origin  The origin as returned by ut_encode_time().
 3201  * Returns:
 3202  *  NULL    Failure.  "ut_get_status()" will be
 3203  *          UT_BAD_ARG      "unit" is NULL.
 3204  *          UT_OS       Operating-system error.  See "errno".
 3205  *          UT_MEANINGLESS  Creation of a timestamp unit based on
 3206  *                  "unit" is not meaningful.
 3207  *          UT_NO_SECOND    The associated unit-system doesn't
 3208  *                  contain a "second" unit.  See
 3209  *                  ut_set_second().
 3210  *  else    Pointer to the resulting unit.  The pointer should be passed
 3211  *      to ut_free() when the unit is no longer needed by the client.
 3212  */
 3213 ut_unit*
 3214 ut_offset_by_time(
 3215     const ut_unit* const    unit,
 3216     const double        origin)
 3217 {
 3218     ut_unit*        result = NULL;  /* failure */
 3219 
 3220     ut_set_status(UT_SUCCESS);
 3221 
 3222     if (unit == NULL) {
 3223     ut_set_status(UT_BAD_ARG);
 3224     ut_handle_error_message("ut_offset_by_time(): NULL unit argument");
 3225     }
 3226     else {
 3227     result = timestampNewOrigin(unit, origin);
 3228     }
 3229 
 3230     return result;
 3231 }
 3232 
 3233 
 3234 /*
 3235  * Returns the result of multiplying one unit by another unit.
 3236  *
 3237  * Arguments:
 3238  *  unit1   Pointer to a unit.
 3239  *  unit2   Pointer to another unit.
 3240  * Returns:
 3241  *  NULL    Failure.  "ut_get_status()" will be:
 3242  *          UT_BAD_ARG      "unit1" or "unit2" is NULL.
 3243  *          UT_NOT_SAME_SYSTEM  "unit1" and "unit2" belong to
 3244  *                  different unit-systems.
 3245  *          UT_OS       Operating-system error. See "errno".
 3246  *  else    Pointer to the resulting unit.  The pointer should be passed
 3247  *      to ut_free() when the unit is no longer needed by the client.
 3248  */
 3249 ut_unit*
 3250 ut_multiply(
 3251     const ut_unit* const    unit1,
 3252     const ut_unit* const    unit2)
 3253 {
 3254     ut_unit*    result = NULL;  /* failure */
 3255 
 3256     ut_set_status(UT_SUCCESS);
 3257 
 3258     if (unit1 == NULL || unit2 == NULL) {
 3259     ut_set_status(UT_BAD_ARG);
 3260     ut_handle_error_message("ut_multiply(): NULL argument");
 3261     }
 3262     else if (unit1->common.system != unit2->common.system) {
 3263     ut_set_status(UT_NOT_SAME_SYSTEM);
 3264     ut_handle_error_message(
 3265             "ut_multiply(): Units in different unit-systems");
 3266     }
 3267     else {
 3268     result = MULTIPLY(unit1, unit2);
 3269     }
 3270 
 3271     return result;
 3272 }
 3273 
 3274 
 3275 /*
 3276  * Returns the inverse (i.e., reciprocal) of a unit.  This convenience function
 3277  * is equal to "ut_raise(unit, -1)".
 3278  *
 3279  * Arguments:
 3280  *  unit    Pointer to the unit.
 3281  * Returns:
 3282  *  NULL    Failure.  "ut_get_status()" will be:
 3283  *          UT_BAD_ARG      "unit" is NULL.
 3284  *          UT_OS       Operating-system error. See "errno".
 3285  *  else    Pointer to the resulting unit.  The pointer should be passed to
 3286  *      ut_free() when the unit is no longer needed by the client.
 3287  */
 3288 ut_unit*
 3289 ut_invert(
 3290     const ut_unit* const    unit)
 3291 {
 3292     return ut_raise(unit, -1);
 3293 }
 3294 
 3295 
 3296 /*
 3297  * Returns the result of dividing one unit by another unit.  This convenience
 3298  * function is equivalent to the following sequence:
 3299  *     {
 3300  *         ut_unit* inverse = ut_invert(denom);
 3301  *         ut_multiply(numer, inverse);
 3302  *         ut_free(inverse);
 3303  *     }
 3304  *
 3305  * Arguments:
 3306  *  numer   Pointer to the numerator (top, dividend) unit.
 3307  *  denom   Pointer to the denominator (bottom, divisor) unit.
 3308  * Returns:
 3309  *  NULL    Failure.  "ut_get_status()" will be:
 3310  *          UT_BAD_ARG      "numer" or "denom" is NULL.
 3311  *          UT_NOT_SAME_SYSTEM  "unit1" and "unit2" belong to
 3312  *                  different unit-systems.
 3313  *          UT_OS       Operating-system error. See "errno".
 3314  *  else    Pointer to the resulting unit.  The pointer should be passed to
 3315  *      ut_free() when the unit is no longer needed by the client.
 3316  */
 3317 ut_unit*
 3318 ut_divide(
 3319     const ut_unit* const    numer,
 3320     const ut_unit* const    denom)
 3321 {
 3322     ut_unit*    result = NULL;      /* failure */
 3323 
 3324     ut_set_status(UT_SUCCESS);
 3325 
 3326     if (numer == NULL || denom == NULL) {
 3327     ut_set_status(UT_BAD_ARG);
 3328     ut_handle_error_message("ut_divide(): NULL argument");
 3329     }
 3330     else if (numer->common.system != denom->common.system) {
 3331     ut_set_status(UT_NOT_SAME_SYSTEM);
 3332     ut_handle_error_message("ut_divide(): Units in different unit-systems");
 3333     }
 3334     else {
 3335     ut_unit*    inverse = RAISE(denom, -1);
 3336 
 3337     if (inverse != NULL) {
 3338         result = MULTIPLY(numer, inverse);
 3339 
 3340         ut_free(inverse);
 3341     }
 3342     }
 3343 
 3344     return result;
 3345 }
 3346 
 3347 
 3348 /*
 3349  * Returns the result of raising a unit to a power.
 3350  *
 3351  * Arguments:
 3352  *  unit    Pointer to the unit.
 3353  *  power   The power by which to raise "unit".  Must be greater than or
 3354  *      equal to -255 and less than or equal to 255.
 3355  * Returns:
 3356  *  NULL    Failure.  "ut_get_status()" will be:
 3357  *          UT_BAD_ARG      "unit" is NULL, or "power" is invalid.
 3358  *          UT_OS       Operating-system error. See "errno".
 3359  *  else    Pointer to the resulting unit.  The pointer should be passed to
 3360  *      ut_free() when the unit is no longer needed by the client.
 3361  */
 3362 ut_unit*
 3363 ut_raise(
 3364     const ut_unit* const    unit,
 3365     const int           power)
 3366 {
 3367     ut_unit*        result = NULL;  /* failure */
 3368 
 3369     ut_set_status(UT_SUCCESS);
 3370 
 3371     if (unit == NULL) {
 3372     ut_set_status(UT_BAD_ARG);
 3373     ut_handle_error_message("ut_raise(): NULL unit argument");
 3374     }
 3375     else if (power < -255 || power > 255) {
 3376     ut_set_status(UT_BAD_ARG);
 3377     ut_handle_error_message("ut_raise(): Invalid power argument");
 3378     }
 3379     else {
 3380     result =
 3381         power == 0
 3382         ? unit->common.system->one
 3383         : power == 1
 3384             ? CLONE(unit)
 3385             : RAISE(unit, power);
 3386     }
 3387 
 3388     return result;
 3389 }
 3390 
 3391 
 3392 /*
 3393  * Returns the result of taking the root of a unit.
 3394  *
 3395  * Arguments:
 3396  *  unit    Pointer to the unit.
 3397  *  root    The root to take of "unit".  Must be greater than or
 3398  *      equal to 1 and less than or equal to 255.
 3399  * Returns:
 3400  *  NULL    Failure.  "ut_get_status()" will be:
 3401  *          UT_BAD_ARG      "unit" is NULL, or "root" is invalid.
 3402  *                              In particular, all powers of base units
 3403  *                              in "unit" must be integral multiples of
 3404  *                              "root".
 3405  *          UT_OS       Operating-system error. See "errno".
 3406  *  else    Pointer to the resulting unit.  The pointer should be passed to
 3407  *      ut_free() when the unit is no longer needed by the client.
 3408  */
 3409 ut_unit*
 3410 ut_root(
 3411     const ut_unit* const    unit,
 3412     const int           root)
 3413 {
 3414     ut_unit*        result = NULL;  /* failure */
 3415 
 3416     ut_set_status(UT_SUCCESS);
 3417 
 3418     if (unit == NULL) {
 3419     ut_set_status(UT_BAD_ARG);
 3420     ut_handle_error_message("ut_root(): NULL unit argument");
 3421     }
 3422     else if (root < 1 || root > 255) {
 3423     ut_set_status(UT_BAD_ARG);
 3424     ut_handle_error_message("ut_root(): Invalid root argument");
 3425     }
 3426     else {
 3427     result =
 3428         root == 1
 3429         ? CLONE(unit)
 3430                 : ROOT(unit, root);
 3431     }
 3432 
 3433     return result;
 3434 }
 3435 
 3436 
 3437 /*
 3438  * Returns the logarithmic unit corresponding to a logarithmic base and a
 3439  * reference level.  For example, the following creates a decibel unit with a
 3440  * one milliwatt reference level:
 3441  *
 3442  *     const ut_unit* watt = ...;
 3443  *     const ut_unit* milliWatt = ut_scale(0.001, watt);
 3444  *
 3445  *     if (milliWatt != NULL) {
 3446  *         const ut_unit* bel_1_mW = ut_log(10.0, milliWatt);
 3447  *
 3448  *         if (bel_1_mW != NULL) {
 3449  *             const ut_unit* decibel_1_mW = ut_scale(0.1, bel_1_mW);
 3450  *
 3451  *             if (decibel_1_mW != NULL) {
 3452  *                 ...
 3453  *                 ut_free(decibel_1_mW);
 3454  *             }            // "decibel_1_mW" allocated
 3455  *
 3456  *             ut_free(bel_1_mW);
 3457  *         }                // "bel_1_mW" allocated
 3458  *
 3459  *         ut_free(milliWatt);
 3460  *     }                // "milliWatt" allocated
 3461  *
 3462  * Arguments:
 3463  *  base        The logarithmic base (e.g., 2, M_E, 10).  Must be
 3464  *                      greater than one.  "M_E" is defined in <math.h>.
 3465  *  reference   Pointer to the reference value as a unit.
 3466  * Returns:
 3467  *  NULL        Failure.  "ut_get_status()" will be:
 3468  *              UT_BAD_ARG      "base" is invalid or "reference"
 3469  *                                              is NULL.
 3470  *              UT_OS       Operating-system error. See
 3471  *                      "errno".
 3472  *  else        Pointer to the resulting unit.  The pointer should be
 3473  *          passed to ut_free() when the unit is no longer needed by
 3474  *          the client.
 3475  */
 3476 ut_unit*
 3477 ut_log(
 3478     const double        base,
 3479     const ut_unit* const    reference)
 3480 {
 3481     ut_unit*        result = NULL;  /* failure */
 3482 
 3483     ut_set_status(UT_SUCCESS);
 3484 
 3485     if (base <= 1) {
 3486     ut_set_status(UT_BAD_ARG);
 3487     ut_handle_error_message("ut_log(): Invalid logarithmic base, %g", base);
 3488     }
 3489     else if (reference == NULL) {
 3490     ut_set_status(UT_BAD_ARG);
 3491     ut_handle_error_message("ut_log(): NULL reference argument");
 3492     }
 3493     else {
 3494     result = logNew(base, reference);
 3495     }
 3496 
 3497     return result;
 3498 }
 3499 
 3500 
 3501 /*
 3502  * Indicates if numeric values in one unit are convertible to numeric values in
 3503  * another unit via "ut_get_converter()".  In making this determination,
 3504  * dimensionless units are ignored.
 3505  *
 3506  * Arguments:
 3507  *  unit1       Pointer to a unit.
 3508  *  unit2       Pointer to another unit.
 3509  * Returns:
 3510  *  0       Failure.  "ut_get_status()" will be
 3511  *                  UT_BAD_ARG      "unit1" or "unit2" is NULL.
 3512  *              UT_NOT_SAME_SYSTEM  "unit1" and "unit2" belong to
 3513  *                      different unit-sytems.
 3514  *              UT_SUCCESS      Conversion between the units is
 3515  *                      not possible (e.g., "unit1" is
 3516  *                      "meter" and "unit2" is
 3517  *                      "kilogram").
 3518  *  else    Numeric values can be converted between the units.
 3519  */
 3520 int
 3521 ut_are_convertible(
 3522     const ut_unit* const    unit1,
 3523     const ut_unit* const    unit2)
 3524 {
 3525     int         areConvertible = 0;
 3526 
 3527     if (unit1 == NULL || unit2 == NULL) {
 3528     ut_set_status(UT_BAD_ARG);
 3529     ut_handle_error_message("ut_are_convertible(): NULL unit argument");
 3530     }
 3531     else if (unit1->common.system != unit2->common.system) {
 3532     ut_set_status(UT_NOT_SAME_SYSTEM);
 3533     ut_handle_error_message(
 3534         "ut_are_convertible(): Units in different unit-systems");
 3535     }
 3536     else {
 3537     ut_set_status(UT_SUCCESS);
 3538 
 3539     if (IS_TIMESTAMP(unit1) || IS_TIMESTAMP(unit2)) {
 3540         areConvertible = IS_TIMESTAMP(unit1) && IS_TIMESTAMP(unit2);
 3541     }
 3542     else {
 3543         ProductRelationship relationship =
 3544         productRelationship(GET_PRODUCT(unit1), GET_PRODUCT(unit2));
 3545 
 3546         areConvertible = relationship == PRODUCT_EQUAL ||
 3547         relationship == PRODUCT_INVERSE;
 3548     }
 3549     }
 3550 
 3551     return areConvertible;
 3552 }
 3553 
 3554 
 3555 /*
 3556  * Returns a converter of numeric values in one unit to numeric values in
 3557  * another unit.  The returned converter should be passed to cv_free() when it
 3558  * is no longer needed by the client.
 3559  *
 3560  * NOTE:  Leap seconds are not taken into account when converting between
 3561  * timestamp units.
 3562  *
 3563  * Arguments:
 3564  *  from        Pointer to the unit from which to convert values.
 3565  *  to      Pointer to the unit to which to convert values.
 3566  * Returns:
 3567  *  NULL        Failure.  "ut_get_status()" will be:
 3568  *              UT_BAD_ARG      "from" or "to" is NULL.
 3569  *              UT_NOT_SAME_SYSTEM  "from" and "to" belong to
 3570  *                      different unit-systems.
 3571  *              UT_MEANINGLESS  Conversion between the units is
 3572  *                      not possible.  See
 3573  *                      "ut_are_convertible()".
 3574  *  else        Pointer to the appropriate converter.  The pointer
 3575  *          should be passed to cv_free() when no longer needed by
 3576  *          the client.
 3577  */
 3578 cv_converter*
 3579 ut_get_converter(
 3580     ut_unit* const  from,
 3581     ut_unit* const  to)
 3582 {
 3583     cv_converter*   converter = NULL;   /* failure */
 3584 
 3585     if (from == NULL || to == NULL) {
 3586     ut_set_status(UT_BAD_ARG);
 3587     ut_handle_error_message("ut_get_converter(): NULL unit argument");
 3588     }
 3589     else if (from->common.system != to->common.system) {
 3590     ut_set_status(UT_NOT_SAME_SYSTEM);
 3591     ut_handle_error_message(
 3592         "ut_get_converter(): Units in different unit-systems");
 3593     }
 3594     else {
 3595     ut_set_status(UT_SUCCESS);
 3596 
 3597     if (!IS_TIMESTAMP(from) && !IS_TIMESTAMP(to)) {
 3598         ProductRelationship relationship =
 3599         productRelationship(GET_PRODUCT(from), GET_PRODUCT(to));
 3600 
 3601         if (relationship == PRODUCT_UNCONVERTIBLE) {
 3602         ut_set_status(UT_MEANINGLESS);
 3603         ut_handle_error_message(
 3604                     "ut_get_converter(): Units not convertible");
 3605         }
 3606         else if (ENSURE_CONVERTER_TO_PRODUCT(from) &&
 3607             ENSURE_CONVERTER_FROM_PRODUCT(to)) {
 3608         if (relationship == PRODUCT_EQUAL) {
 3609             converter = cv_combine(
 3610             from->common.toProduct, to->common.fromProduct);
 3611         }
 3612         else {
 3613             /*
 3614              * The underlying product-units are reciprocals of each
 3615              * other.
 3616              */
 3617             cv_converter*   invert = cv_get_inverse();
 3618 
 3619             if (invert != NULL) {
 3620             cv_converter*   phase1 =
 3621                 cv_combine(from->common.toProduct, invert);
 3622 
 3623             if (phase1 != NULL) {
 3624                 converter =
 3625                 cv_combine(phase1, to->common.fromProduct);
 3626 
 3627                 cv_free(phase1);
 3628             }       /* "phase1" allocated */
 3629 
 3630             cv_free(invert);
 3631             }           /* "invert" allocated */
 3632         }           /* reciprocal product-units */
 3633 
 3634         if (converter == NULL) {
 3635             ut_set_status(UT_OS);
 3636             ut_handle_error_message(strerror(errno));
 3637             ut_handle_error_message(
 3638             "ut_get_converter(): Couldn't get converter");
 3639         }
 3640         }               /* got necessary product converters */
 3641     }               /* neither unit is a timestamp */
 3642     else {
 3643         cv_converter*   toSeconds =
 3644                 ut_get_converter(from->timestamp.unit,
 3645                     from->common.system->second);
 3646 
 3647         if (toSeconds == NULL) {
 3648         ut_set_status(UT_OS);
 3649         ut_handle_error_message(strerror(errno));
 3650         ut_handle_error_message(
 3651             "ut_get_converter(): Couldn't get converter to seconds");
 3652         }
 3653         else {
 3654         cv_converter*   shiftOrigin =
 3655             cv_get_offset(
 3656             from->timestamp.origin - to->timestamp.origin);
 3657 
 3658         if (shiftOrigin == NULL) {
 3659             ut_set_status(UT_OS);
 3660             ut_handle_error_message(strerror(errno));
 3661             ut_handle_error_message(
 3662             "ut_get_converter(): Couldn't get offset-converter");
 3663         }
 3664         else {
 3665             cv_converter*   toToUnit =
 3666             cv_combine(toSeconds, shiftOrigin);
 3667 
 3668             if (toToUnit == NULL) {
 3669             ut_set_status(UT_OS);
 3670             ut_handle_error_message(strerror(errno));
 3671             ut_handle_error_message(
 3672                 "ut_get_converter(): Couldn't combine converters");
 3673             }
 3674             else {
 3675             cv_converter*   fromSeconds = ut_get_converter(
 3676                 to->common.system->second, to->timestamp.unit);
 3677 
 3678             if (fromSeconds == NULL) {
 3679                 ut_set_status(UT_OS);
 3680                 ut_handle_error_message(strerror(errno));
 3681                 ut_handle_error_message(
 3682                 "ut_get_converter(): Couldn't get converter "
 3683                 "from seconds");
 3684             }
 3685             else {
 3686                 converter = cv_combine(toToUnit, fromSeconds);
 3687 
 3688                 if (converter == NULL) {
 3689                 ut_set_status(UT_OS);
 3690                 ut_handle_error_message(strerror(errno));
 3691                 ut_handle_error_message("ut_get_converter(): "
 3692                     "Couldn't combine converters");
 3693                 }
 3694 
 3695                 cv_free(fromSeconds);
 3696             }       /* "fromSeconds" allocated */
 3697 
 3698             cv_free(toToUnit);
 3699             }           /* "toToUnit" allocated */
 3700 
 3701             cv_free(shiftOrigin);
 3702         }           /* "shiftOrigin" allocated */
 3703 
 3704         cv_free(toSeconds);
 3705         }               /* "toSeconds" allocated */
 3706     }               /* units are timestamps */
 3707     }                   /* valid arguments */
 3708 
 3709     return converter;
 3710 }
 3711 
 3712 
 3713 /*
 3714  * Indicates if a given unit is dimensionless or not.  Note that logarithmic
 3715  * units are dimensionless by definition.
 3716  *
 3717  * Arguments:
 3718  *  unit    Pointer to the unit in question.
 3719  * Returns:
 3720  *  0   "unit" is dimensionfull or an error occurred.  "ut_get_status()"
 3721  *       will be
 3722  *          UT_BAD_ARG      "unit" is NULL.
 3723  *          UT_SUCCESS      "unit" is dimensionfull.
 3724  *  else    "unit" is dimensionless.
 3725  */
 3726 int
 3727 ut_is_dimensionless(
 3728     const ut_unit* const    unit)
 3729 {
 3730     int     isDimensionless = 0;
 3731 
 3732     ut_set_status(UT_SUCCESS);
 3733 
 3734     if (unit == NULL) {
 3735     ut_set_status(UT_BAD_ARG);
 3736     ut_handle_error_message("ut_is_dimensionless(): NULL unit argument");
 3737     }
 3738     else {
 3739     /*
 3740      * Special case logarithmic units because logGetProduct() can be
 3741      * dimensionfull.
 3742      */
 3743     isDimensionless =
 3744         IS_LOG(unit)
 3745         ? 1
 3746         : productIsDimensionless(GET_PRODUCT(unit));
 3747     }
 3748 
 3749     return isDimensionless;
 3750 }
 3751 
 3752 
 3753 /*
 3754  * Returns a clone of a unit.
 3755  *
 3756  * Arguments:
 3757  *  unit    Pointer to the unit to be cloned.
 3758  * Returns:
 3759  *  NULL    Failure.  ut_get_status() will be
 3760  *          UT_OS   Operating-system failure.  See "errno".
 3761  *          UT_BAD_ARG  "unit" is NULL.
 3762  *  else    Pointer to the clone of "unit".  The pointer should be
 3763  *      passed to ut_free() when the unit is no longer needed by the
 3764  *      client.
 3765  */
 3766 ut_unit*
 3767 ut_clone(
 3768     const ut_unit* const    unit)
 3769 {
 3770     ut_unit*    clone = NULL;       /* failure */
 3771 
 3772     ut_set_status(UT_SUCCESS);
 3773 
 3774     if (unit == NULL) {
 3775     ut_set_status(UT_BAD_ARG);
 3776     ut_handle_error_message("ut_clone(): NULL unit argument");
 3777     }
 3778     else {
 3779     clone =
 3780         unit == unit->common.system->one
 3781         ? (ut_unit*)unit
 3782         : CLONE(unit);
 3783     }
 3784 
 3785     return clone;
 3786 }
 3787 
 3788 
 3789 /*
 3790  * Frees resources associated with a unit.  This function should be invoked on
 3791  * all units that are no longer needed by the client.  Use of the unit upon
 3792  * return from this function will result in undefined behavior.
 3793  *
 3794  * Arguments:
 3795  *  unit    Pointer to the unit to have its resources freed or NULL.
 3796  */
 3797 void
 3798 ut_free(
 3799     ut_unit* const  unit)
 3800 {
 3801     ut_set_status(UT_SUCCESS);
 3802 
 3803     if (unit != NULL) {
 3804     if (unit != unit->common.system->one)
 3805         FREE(unit);
 3806     }
 3807 }
 3808 
 3809 
 3810 /*
 3811  * Accepts a visitor to a unit.
 3812  *
 3813  * Arguments:
 3814  *  unit        Pointer to the unit to accept the visitor.
 3815  *  visitor     Pointer to the visitor of "unit".
 3816  *  arg     An arbitrary pointer that will be passed to "visitor".
 3817  * Returns:
 3818  *  UT_BAD_ARG  "unit" or "visitor" is NULL.
 3819  *  UT_VISIT_ERROR  A error occurred in "visitor" while visiting "unit".
 3820  *  UT_SUCCESS  Success.
 3821  */
 3822 ut_status
 3823 ut_accept_visitor(
 3824     const ut_unit* const    unit,
 3825     const ut_visitor* const visitor,
 3826     void* const         arg)
 3827 {
 3828     ut_set_status(UT_SUCCESS);
 3829 
 3830     if (unit == NULL || visitor == NULL) {
 3831     ut_set_status(UT_BAD_ARG);
 3832     ut_handle_error_message("ut_accept_visitor(): NULL argument");
 3833     }
 3834     else {
 3835     ut_set_status(ACCEPT_VISITOR(unit, visitor, arg));
 3836     }
 3837 
 3838     return ut_get_status();
 3839 }