Skip to content

Adapting Codac to GAOL 4.3.2 and GAOL v5 #8

Description

@Jordan08

Codac builds today against the GAOL 4.2 of Frédéric Goualard. This issue summarizes what a code using GAOL has to adapt to move to GAOL 4.3.2 (branch master of Jordan08/GAOL) or to GAOL v5 (branch MATH-CORE). GAOL 4.3.2 is a direct ancestor of GAOL v5, so everything in the first section is included in the second. Each change is detailed, with its reasons and its measurements, in doc/differences.md, and the manual of GAOL v5 has a chapter Moving a program from GAOL 4 to GAOL v5.

GAOL 4.2 → GAOL 4.3.2 (branch master)

No source change is needed: gaol/gaol.h still opens namespace gaol, and the headers, types and functions are unchanged. C++11 is required (the throw() exception specifications are gone). Recompiling is enough.

Build and link

  • The patch IBEX applies to GAOL (gaol-4.2.3alpha0.all.all.patch) is integrated and must not be applied: the FPU is initialised with fesetenv(), the macro opposite() is renamed gaol_opposite(), and interval::midpoint() and operator<< set the rounding direction back upward.
  • A CMake build exists: find_package(gaol) gives the target gaol::gaol, which carries the flags of interval arithmetic; mathlib is built with GAOL from 3rd/mathlib and exported as gaol::ultim. The option GAOL_FIND_MATHLIB=OFF builds and installs mathlib with GAOL even where one is installed, for Codac's build, which expects libultim and MathLib.h under the prefix it gives. Each build installs a gaol.pc for pkg-config.
  • The rounding direction is no longer the caller's business: each operation sets it upward itself, and leaves it upward. A code computing its own floating point to nearest between GAOL calls either accepts that, or builds GAOL with GAOL_PRESERVE_ROUNDING, which — unlike the "preserve" of GAOL 4 — really restores the caller's direction, SSE register included.
  • gaol::intervalf and gaol::interval2f are compiled only with GAOL_FLOAT_INTERVALS (Codac uses neither).
  • gaol/gaol_config.h refuses the configurations that give wrong bounds (Clang for 32-bit ARM, MinGW-w64 older than 12, /fp:fast…).

Results that change

Regression baselines may move; two idioms have to be audited:

  • ⚠️ The intersection of disjoint intervals is the empty set [NaN, NaN] rather than reversed bounds ([3, 2]): code reading the bounds of an empty intersection, or testing left() > right(), must go through is_empty().
  • ⚠️ width() of the empty set is NaN rather than −1.
  • Tighter bounds: sin/cos/tan within one double of the tightest at every magnitude, integer powers and nth roots proved from exact products, sqrt the tightest, exp(0) = 1 and log(1) = 0 exact, pow(x, -n) without overflow.
  • atan2() is implemented (it raised unavailable_feature_error).
  • The constructors give the empty set for interval(+oo), interval(2, 1) and NaN bounds, as IBEX's patch imposed.
  • pow(I, double) no longer truncates the exponent to an int, and pow(I, J) keeps the negative part of the base for an integer exponent only — the fix ported from Codac (74086cc), which Codac can drop from its own wrapper.
  • nth_root of an odd order is defined on the whole real line (the rootn of IEEE 1788-2015); log of an interval holding no positive number is empty; the comparisons follow Tables 10.3 and 10.4 of IEEE 1788-2015 for empty sets and infinite bounds (certainly_leq() is true when either interval is empty); a zero bound times an infinite one counts as 0.
  • Input/output: the interval literals of IEEE 1788-2015 are read ([empty], [1,], 0x1.3p-1, 3.56?1; "[inf]" is the empty set), numbers are read exactly on every C library, and the decimal output is rounded outward on every C library.
  • Added or fixed: rad() and mid_rad(), mid(), hausdorff(), div_rel(), invabs_rel(), uipow() exported.

GAOL 4.3.2 → GAOL v5 (branch MATH-CORE)

All of the above, plus real source adaptations:

  1. gaol/gaol.h no longer opens namespace gaol. Add using namespace gaol;, or name gaol::interval; open exactly one of gaol and gaol_ieee1788, their pow being ambiguous with both. Code that already qualifies gaol:: compiles unchanged. The symbols of the library name gaol_core: every client is compiled again, there is no binary compatibility.
  2. == and != on intervals are removed, with the possibly relations (possibly_eq()…), certainly_eq(), certainly_neq() and the option --enable-relations. A program compares intervals with set_eq(), set_disjoint() and !set_disjoint(); <, <=, > and >= are the certainly relations in every build. A leftover == stops the compilation, so nothing passes silently.
  3. No mathematical library is left to find, build or link: mathlib is gone, CORE-MATH is compiled into libgaol. For Codac: GAOL_FIND_MATHLIB, gaol::ultim, libultim and MathLib.h no longer exist; gaol::gaol is linked alone (PUBLIC for a library whose headers include GAOL's, so that its own users get the flags). GAOL can also be brought in by FetchContent, with no network access beyond its sources.
  4. The hexa output format writes interval literals ([0x1.999999999999ap-4, …]), read back bit for bit as IEEE 1788-2015 requires, rather than the sixteen raw hexadecimal digits of each double. The decimal formats and the default one are unchanged.
  5. One grammar reads every string: "1+[1,2]" and "[cos([0,1]), 2]" are read where GAOL 4 refused them, the reader knows every function of GAOL, gaol::textToInterval() is added, and gaol_ieee1788::textToInterval() reads the names of the standard (pown, rootn, sinPi…). Several threads can read strings at once, where GAOL 4 crashed.
  6. New operations: exp2, log2, exp10, log10, fifteen functions of Table 10.5 (expm1, log1p, hypot, rsqrt, sinpi, atan2pi…), fma, cancelMinus/cancelPlus, sign, trunc, round_ties_to_even/_away, and the namespace gaol_ieee1788, which gives every operation the name, the argument order and the semantics of IEEE 1788-2015.
  7. Tightest bounds everywhere: the elementary functions are correctly rounded (CORE-MATH) and exact where their value is a double, rather than one double beyond. Expected bounds hard-coded in tests may move by one or two doubles, always inward.
  8. With C++17, GAOL_NODISCARD warns on an ignored result (sqrt(I); alone).

Performance, in passing: GAOL v5 is markedly faster where GAOL 4 suffered — the elementary functions are 3 to 10 times faster with MinGW-w64 and Visual C++, the rounding direction being written to the x86 control registers rather than through fesetround().

Summary for Codac

  • To 4.3.2: recompile against it, stop applying local fixes GAOL now carries (the pow fix, IBEX's patch), and audit the two empty-set idioms (width() == -1, bounds of an empty intersection).
  • To v5: additionally add using namespace gaol; where the code counted on gaol.h opening it, replace ==/!= and the possibly relations with the set relations, and remove mathlib from the build — libgaol is the only library left to link.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions