Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/audit/compare.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
'GAOL_HAVE_GETRUSAGE', 'GAOL_HAVE_ROUNDING_MATH_OPTION', 'GAOL_HAVE_VISIBILITY_OPTIONS',
'GAOL_USING_SSE2_INSTRUCTIONS', 'GAOL_USING_SSE3_INSTRUCTIONS', 'GAOL_WORDS_BIGENDIAN', 'GAOL_RND_PROBE',
'GAOL_HAVE_AVX512_TARGET', 'GAOL_PREFER_AVX512',
'NDEBUG', '_GLIBCXX_ASSERTIONS', '__FAST_MATH__', '__OPTIMIZE__', '__SSE2_MATH__', '__STRICT_ANSI__')
'NDEBUG', '_GLIBCXX_ASSERTIONS', '__FAST_MATH__', '__FINITE_MATH_ONLY__', '__OPTIMIZE__', '__SSE2_MATH__', '__STRICT_ANSI__')
# The macros compared by value
VALUES = ('GAOL_SIZEOF_INT', 'GAOL_SIZEOF_LONG_LONG_INT', 'FLT_EVAL_METHOD', '__cplusplus',
'GAOL_MAJOR_VERSION', 'GAOL_MINOR_VERSION', 'GAOL_MICRO_VERSION', 'GAOL_VERSION')
Expand Down
2 changes: 1 addition & 1 deletion .github/audit/make_probe.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
'GAOL_USING_SSE2_INSTRUCTIONS', 'GAOL_USING_SSE3_INSTRUCTIONS', 'GAOL_WORDS_BIGENDIAN', 'GAOL_RND_PROBE', 'GAOL_RND_SSE_REGISTER']
# Compared by value only (GAOL_VERSION is a string, which #if cannot read)
text = ['GAOL_INLINE', 'GAOL_PUBLIC', 'GAOL_MAJOR_VERSION', 'GAOL_MINOR_VERSION', 'GAOL_MICRO_VERSION', 'GAOL_VERSION']
compiler = ['__cplusplus', '__STRICT_ANSI__', '__OPTIMIZE__', 'NDEBUG', '_GLIBCXX_ASSERTIONS', '__FAST_MATH__', 'FLT_EVAL_METHOD',
compiler = ['__cplusplus', '__STRICT_ANSI__', '__OPTIMIZE__', 'NDEBUG', '_GLIBCXX_ASSERTIONS', '__FAST_MATH__', '__FINITE_MATH_ONLY__', 'FLT_EVAL_METHOD',
'__SSE2__', '__SSE3__', '__SSE2_MATH__', '__PIC__', '__x86_64__', '__i386__', '__aarch64__', '__arm__', '__APPLE__',
'__linux__', '_WIN32', '__MINGW64_VERSION_MAJOR']
lines = ['#include <cfloat>', '#include "gaol/gaol.h"']
Expand Down
3 changes: 2 additions & 1 deletion doc/building.md
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,8 @@ The three builds have the same targets:
CppUnit: they are in `tests/` now, and need nothing (see
[The tests](tests.md)). `ctest` runs the tests and the examples of a CMake
build; `make test` leaves the examples out (label `example`, CMake 3.17 and
later). With meson before 0.57, `meson test` runs the examples too, and
later), and runs the compile tests `refused_*` and `nodiscard_*` too. With
meson before 0.57, `meson test` runs the examples too, and
`meson test --suite unit` the tests alone.
- **The examples** check what they print and fail otherwise (see
[examples/examples.md](../examples/examples.md)).
Expand Down
4 changes: 2 additions & 2 deletions doc/continuous-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ refuse Clang on 32-bit ARM and Clang 14 on 64-bit ARM, that
`gaol/gaol_config.h` refuses MinGW-w64 GCC 11 to 13 and MSYS2 MINGW64 (GCC
and Clang) on x64 and GCC 11 on x86,
`-ffinite-math-only` and `-ffast-math` with GCC and Clang (the tests
`refused_finite_math_only` and `refused_fast_math` of `make test`), and Visual
C++ and clang-cl without `/fp:strict`. Jobs of each build
`refused_*` of the three builds, see [Tests](tests.md)), and Visual C++ and
clang-cl without `/fp:strict`. Jobs of each build
restore the rounding direction (`GAOL_PRESERVE_ROUNDING`): Ubuntu x86_64 GCC
and arm64 Clang, Debian i386 and armhf, macOS arm64, Visual Studio x64,
autotools and meson. The jobs built in Release print the time per operation in
Expand Down
30 changes: 18 additions & 12 deletions doc/tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -675,20 +675,26 @@ mode there.
and read a file holding NUL bytes, meson stripped the blanks of Unicode,
autoconf dropped the blanks within the version and let NUL bytes through,
took `5.0.0)` for 5.0.0 and stopped on a bracket) (GAOL v5).
- **`refused_finite_math_only` and `refused_fast_math`:** compile tests, made
by the CMake build where the compiler is GCC or Clang. `tests/refused_options.cpp`,
a program including `<gaol/gaol>`, is compiled with `-ffinite-math-only` and
- **`refused_finite_math_only`, `refused_fast_math` and `refused_positive`**
(CMake build), **`refused_options.sh`** (autotools build) and
**`refused_options`** (meson build): compile tests, where the compiler is GCC
or Clang (the script skips another one). `tests/refused_options.cpp`, a
program including `<gaol/gaol>`, is compiled with `-ffinite-math-only` and
with `-ffast-math`, put after the flags of interval arithmetic, and the
compilation has to fail with the message of `gaol/gaol_config.h`, which the
test looks for in the output of the build. With `-ffinite-math-only` the
compiler takes NaN and infinities never to occur, in the inline functions of
the headers too, and the empty interval, whose bounds are NaN, is no longer
told empty: `([1, 2] & [3, 4]).is_empty()` was false with GCC 9 and Clang 18.
The header did not refuse `-ffinite-math-only`, nor `-Ofast` or `-ffast-math`
followed by `-frounding-math` with Clang, which leave `__FAST_MATH__`
undefined and `__FINITE_MATH_ONLY__` at 1 (GAOL v5). The autotools and meson
builds have no such test, the header being the same; `tests/fp_strict` is
the check of Visual C++ without `/fp:strict`.
test looks for in the output of the compiler; compiled with neither, it has
to compile. The CMake build makes each compilation a target of its own,
built by the test; `tests/refused_options.sh` runs the three compilations in
the autotools and meson builds, with the compiler and the flags of the code
using GAOL. With `-ffinite-math-only` the compiler takes NaN and infinities
never to occur, in the inline functions of the headers too, and the empty
interval, whose bounds are NaN, is no longer told empty:
`([1, 2] & [3, 4]).is_empty()` was false with GCC 9.4 and 13 at `-O0`, `-O2`
and `-O3`, and with Clang 18 at `-O0`, and at `-O2` and `-O3` when the bounds
are `volatile`. The header did not refuse `-ffinite-math-only`, nor `-Ofast`
or `-ffast-math` followed by `-frounding-math` with Clang, which leave
`__FAST_MATH__` undefined and `__FINITE_MATH_ONLY__` at 1 (GAOL v5).
`tests/fp_strict` is the check of Visual C++ without `/fp:strict`.
- **`cpack_stale_configure`** (CMake build, on a Unix system that builds for
itself, where the tree has a `configure`): a script, not a program
(`tests/cpack_stale_configure.cmake`). CPack puts `configure` in the archive
Expand Down
22 changes: 14 additions & 8 deletions doc/three-builds.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,19 +148,25 @@ alone refuses, when compiling:
| Clang for 32-bit ARM processors | It does not honour the rounding direction there: built by Clang 21, 4556 of 16000 random products, squares and cubes did not enclose their exact values. GCC does. |
| A compiler saying of `-frounding-math` "overriding currently unsupported rounding mode on this target", as Clang 14 for 64-bit ARM | Bounds of `pow()` and `nth_root()` did not enclose the exact values. Clang 18 honours the rounding direction there. |
| MinGW-w64 whose `fma()` or `round()` is wrong: on x64, before mingw-w64 12 (GCC 11 to 13 of Chocolatey) and linked with `msvcrt.dll` rather than the UCRT (MSYS2 MINGW64, the cross compilers of Debian and Ubuntu); on 32-bit x86, before 11 (GCC 11 of WinLibs); on ARM, before 11 (not tested) | On x64, the `fma()` and `round()` of mingw-w64's own math library, computed in doubles: that `fma()` is not correctly rounded (10.7 % of the error-free products `fma(a, b, -a*b)` wrong), and CORE-MATH computes with it; that `round()` depends on the rounding direction. On 32-bit x86, the `fma()` of the mingw-w64 9 of WinLibs rounds each of its partial sums to a double. Bounds of `tan()`, `asin()`, `atan()` and others did not enclose the exact values. MinGW-w64 GCC 14 and 15 on x64, 12 to 15 on 32-bit x86, and MSYS2 UCRT64 and CLANG64 are built and tested. |
| `-ffast-math`, `-Ofast`, `/fp:fast` | The compiler then rounds to nearest and drops the checks of NaN and infinities. Linking with them, or with `-funsafe-math-optimizations`, is a matter of its own (below). |
| `-ffinite-math-only`, which `-ffast-math` and `-Ofast` turn on | The compiler then takes NaN and infinities never to occur, in GAOL's inline functions too: the empty interval has NaN bounds, and `([1, 2] & [3, 4]).is_empty()` is false (GCC 9.4, Clang 18). |
| `-ffast-math`, `-Ofast`, `/fp:fast` | The compiler then rounds to nearest and drops the checks of NaN and infinities. `-Ofast` is not refused where `-fno-fast-math` turns its fast-math optimizations off (below). Linking with them, or with `-funsafe-math-optimizations`, is a matter of its own (below). |
| `-ffinite-math-only`, which `-ffast-math` and `-Ofast` turn on | The compiler then takes NaN and infinities never to occur, in GAOL's inline functions too: the empty interval has NaN bounds, and `([1, 2] & [3, 4]).is_empty()` is false (GCC 9.4 and 13 at `-O0`, `-O2` and `-O3`; Clang 18 at `-O0`, and at `-O2` and `-O3` when the bounds are `volatile`). |
| Visual C++, and clang-cl from Clang 16, without `/fp:strict` (`/fp:precise`, their default) | They then assume rounding to nearest, and may evaluate or rewrite floating-point operations accordingly (clang-cl compiles with `-fno-rounding-math -ffp-contract=on`; GAOL v5 did not refuse it at first): no test gave a wrong bound so, but nothing certifies the bounds (see [What differs from GAOL](differences.md)). |
| Doubles computed on the x87 unit of 32-bit x86 processors (without `-msse2 -mfpmath=sse`, or `/arch:SSE2`) | CORE-MATH assumes every operation on doubles rounded to a double. Computed in extended precision, its results rounded to nearest are rounded twice, and 175 arguments gave the other neighbour of the exact value with GCC 12 on Debian 12 i386; with GCC 9, which rounds to nearest at compile time the constants CORE-MATH rounds in the direction in effect, GAOL's bounds of `exp2(-1075)`, `expm1(-800)` or `atan2()` of a tiny and a huge number did not enclose the exact values. `tests/extended_precision.cpp` checks these arguments. |

`-fno-fast-math`, one of the flags of interval arithmetic, turns `-ffast-math`
and `-ffinite-math-only` off when it comes after them on the command line, and
not when it comes before: `gaol.pc` and `gaol::gaol` give it, and the code
including GAOL's headers is refused when the option follows it. The CMake tests
`refused_finite_math_only` and `refused_fast_math` compile
`tests/refused_options.cpp` with each of the two options, after the flags of
interval arithmetic, and check that `gaol/gaol_config.h` refuses it (GCC and
Clang).
not when it comes before them: `gaol.pc` and `gaol::gaol` give it, and the code
including GAOL's headers is refused when `-ffast-math` or `-ffinite-math-only`
comes after `-fno-fast-math`. The CMake tests `refused_finite_math_only` and
`refused_fast_math` compile `tests/refused_options.cpp` with each of the two
options, after the flags of interval arithmetic, and check that
`gaol/gaol_config.h` refuses it, and `refused_positive` that it compiles
without them (GCC and Clang); `tests/refused_options.sh` does the same in the
autotools and meson builds. With GCC, `-fno-fast-math` turns the fast-math
optimizations of `-Ofast` off wherever it stands on the command line, before
`-Ofast` too, and the header has nothing to refuse: of them, GCC 9.4 keeps
only `-fcx-limited-range`, which changes the arithmetic of complex numbers
alone. Clang turns them off only when `-fno-fast-math` comes after `-Ofast`.

No macro of the compiler shows the following, which `gaol/gaol_config.h`
cannot refuse and which give wrong results all the same: the code using GAOL
Expand Down
6 changes: 4 additions & 2 deletions doc/using.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ what contradicts them, `-ffast-math`, `-ffinite-math-only` and doubles computed
on the x87 unit (see
[Compilers and options refused](three-builds.md#compilers-and-options-refused)).
`-fno-fast-math` turns the first two off when it comes after them on the
command line, and does nothing when it comes before them, where the
compilation stops.
command line, and does nothing when `-ffast-math` or `-ffinite-math-only` comes
after `-fno-fast-math`, where the compilation stops. With GCC, it turns the
fast-math optimizations of `-Ofast` off wherever it stands, and `-Ofast` is not
refused there.

With `-frounding-math` on x86, GCC 12.1 to 12.3 and 13.1 to 13.2 (Debian 12
has GCC 12.2) initialize wrongly a double member of a static array of
Expand Down
5 changes: 3 additions & 2 deletions examples/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -1073,8 +1073,9 @@ check:
```

and a row in the refused options of `doc/three-builds.md`. Test: a compile
test with `PASS_REGULAR_EXPRESSION "ffinite-math-only"`, as
`tests/fp_strict` does for other options.
test with `PASS_REGULAR_EXPRESSION "ffinite-math-only"` (`tests/fp_strict`,
the check of Visual C++ and clang-cl without `/fp:strict`, is a
`try_compile()` at configure time instead).

**5. `atanh([1, x])`.** In `atanh()`, return the empty set when
`J.left() == 1.0 || J.right() == -1.0` (J being `I & [-1, 1]`), and write the
Expand Down
27 changes: 15 additions & 12 deletions gaol/gaol_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,21 +191,24 @@
--------------------------------------------------------------------------- */

#if defined(__FAST_MATH__)
# error "GAOL cannot be compiled with -ffast-math (nor -Ofast): the bounds it computes would not enclose the exact results"
# error "GAOL cannot be compiled with -ffast-math (nor -Ofast): the bounds it computes would not enclose the exact results (remove the option, or put -fno-fast-math, one of the flags of gaol.pc and gaol::gaol, after it)"
#endif
/* -ffinite-math-only, which -ffast-math and -Ofast turn on, has the compiler
take NaN and infinities never to occur, in the inline functions of GAOL's
headers as anywhere else: the empty interval has NaN bounds, and is_empty()
reads it as !(left() <= right()). The compiler then folds the test away, and
([1, 2] & [3, 4]).is_empty() is false (GCC 9, Clang 18): the tests
refused_finite_math_only and refused_fast_math (tests/CMakeLists.txt) check
the refusal. GCC and Clang define __FINITE_MATH_ONLY__, as 0 or 1; Visual
C++ defines nothing of the kind (its /fp:fast is refused below). This also
refuses what __FAST_MATH__ does not show: with Clang, -Ofast or -ffast-math
followed by -frounding-math leave it undefined, and __FINITE_MATH_ONLY__ at
1. -fno-fast-math, one of the flags of gaol.pc and gaol::gaol, turns the
option off when it comes after it on the command line, and does nothing when
it comes before.
reads it as !std::islessequal(left(), right()) (std::isunordered() first on
32-bit ARM and POWER9). The compiler then folds the test away, and
([1, 2] & [3, 4]).is_empty() is false: with GCC 9.4 and 13 at -O0, -O2 and
-O3, with Clang 18 at -O0, and at -O2 and -O3 when the bounds are volatile.
The tests refused_finite_math_only and refused_fast_math
(tests/CMakeLists.txt) and tests/refused_options.sh check the refusal. GCC
and Clang define __FINITE_MATH_ONLY__, as 0 or 1; Visual C++ defines nothing
of the kind (its /fp:fast is refused below). This also refuses what
__FAST_MATH__ does not show: with Clang, -Ofast or -ffast-math followed by
-frounding-math leave it undefined, and __FINITE_MATH_ONLY__ at 1.
-fno-fast-math, one of the flags of gaol.pc and gaol::gaol, turns the option
off when the option comes before it on the command line, and does nothing
when the option comes after it, where the compilation stops here.

No macro shows what follows, which GAOL cannot refuse:
-funsafe-math-optimizations and -ffast-math -fno-finite-math-only, with
Expand All @@ -218,7 +221,7 @@
-fno-honor-nans of Clang, given without -fno-honor-infinities, which does to
the empty interval what -ffinite-math-only does. */
#if defined(__FINITE_MATH_ONLY__) && __FINITE_MATH_ONLY__
# error "GAOL cannot be compiled with -ffinite-math-only (which -ffast-math and -Ofast turn on): its empty interval has NaN bounds and its unbounded ones infinite bounds, which the compiler then takes never to occur (-fno-fast-math, one of the flags of gaol.pc and gaol::gaol, turns it off when it comes after)"
# error "GAOL cannot be compiled with -ffinite-math-only (which -ffast-math and -Ofast turn on): its empty interval has NaN bounds and its unbounded ones infinite bounds, which the compiler then takes never to occur (remove the option, or put -fno-fast-math, one of the flags of gaol.pc and gaol::gaol, after the option that turns it on)"
#endif
#if defined(_M_FP_FAST)
# error "GAOL cannot be compiled with /fp:fast: the bounds it computes would not enclose the exact results (it needs /fp:strict)"
Expand Down
13 changes: 10 additions & 3 deletions manual/v5/gaol.tex
Original file line number Diff line number Diff line change
Expand Up @@ -362,8 +362,13 @@ \subsection{Compilers and options refused}\label{sec:refused}
\noindent
\option{-fno-fast-math}, one of the flags of interval arithmetic, turns
\option{-ffast-math} and \option{-ffinite-math-only} off when it comes after
them on the command line, and does nothing when it comes before them, where the
compilation stops. No macro of the compiler shows the following, which
them on the command line, and does nothing when \option{-ffast-math} or
\option{-ffinite-math-only} comes after \option{-fno-fast-math}, where the
compilation stops. With GCC, it turns the fast-math optimizations of
\option{-Ofast} off wherever it stands on the command line, before
\option{-Ofast} too, and \option{-Ofast} is not refused there: of them, GCC~9.4
keeps only \option{-fcx-limited-range}, which changes the arithmetic of complex
numbers alone. No macro of the compiler shows the following, which
\file{gaol/gaol\_config.h} cannot refuse and which give wrong results all the
same: \option{-funsafe-math-optimizations} and \option{-ffast-math
-fno-finite-math-only} with GCC, which rewrites the addition by which GAOL sees
Expand Down Expand Up @@ -1494,7 +1499,9 @@ \subsection{The flags of interval arithmetic}
% c++ -ffast-math -c program.cpp
gaol/gaol_config.h: error: #error "GAOL cannot be
compiled with -ffast-math (nor -Ofast): the bounds it
computes would not enclose the exact results"
computes would not enclose the exact results (remove
the option, or put -fno-fast-math, one of the flags of
gaol.pc and gaol::gaol, after it)"
\end{onscreen}

\noindent
Expand Down
Loading
Loading