blueloveTH 3 stundas atpakaļ
vecāks
revīzija
c036e638cd
54 mainītis faili ar 5681 papildinājumiem un 729 dzēšanām
  1. 21 5
      .github/workflows/main.yml
  2. 70 0
      3rd/openlibm/LICENSE.txt
  3. 131 0
      3rd/openlibm/README.md
  4. 20 0
      3rd/openlibm/SHA256SUMS
  5. 25 1
      CMakeLists.txt
  6. 1 0
      CMakeOptions.txt
  7. 5 1
      amalgamate.py
  8. 1 1
      build_g.sh
  9. 43 5
      include/pocketpy/common/dmath.h
  10. 343 0
      scripts/dmath/cases.py
  11. 104 0
      scripts/dmath/generate.py
  12. 229 0
      scripts/dmath/oracle.py
  13. 5 17
      src/bindings/py_number.c
  14. 13 455
      src/common/dmath.c
  15. 2319 0
      src/common/dmath_openlibm.c
  16. 3 3
      src/common/dmath_zig.c
  17. 22 15
      src/modules/math.c
  18. 436 0
      src2/test_dmath.c
  19. 0 222
      tests/930_deterministic_float.py
  20. 229 0
      tests/930_dmath.py
  21. 4 4
      tests/931_math.py
  22. 73 0
      tests/932_dmath_consumers.py
  23. 148 0
      tests/dmath/README.md
  24. 44 0
      tests/dmath/cases/acos.txt
  25. 44 0
      tests/dmath/cases/asin.txt
  26. 62 0
      tests/dmath/cases/atan.txt
  27. 66 0
      tests/dmath/cases/atan2.txt
  28. 46 0
      tests/dmath/cases/cbrt.txt
  29. 68 0
      tests/dmath/cases/ceil.txt
  30. 47 0
      tests/dmath/cases/copysign.txt
  31. 48 0
      tests/dmath/cases/cos.txt
  32. 55 0
      tests/dmath/cases/exp.txt
  33. 32 0
      tests/dmath/cases/exp10.txt
  34. 46 0
      tests/dmath/cases/exp2.txt
  35. 26 0
      tests/dmath/cases/fabs.txt
  36. 68 0
      tests/dmath/cases/floor.txt
  37. 27 0
      tests/dmath/cases/fmax.txt
  38. 27 0
      tests/dmath/cases/fmin.txt
  39. 52 0
      tests/dmath/cases/fmod.txt
  40. 26 0
      tests/dmath/cases/isfinite.txt
  41. 26 0
      tests/dmath/cases/isinf.txt
  42. 26 0
      tests/dmath/cases/isnan.txt
  43. 30 0
      tests/dmath/cases/isnormal.txt
  44. 33 0
      tests/dmath/cases/log.txt
  45. 34 0
      tests/dmath/cases/log10.txt
  46. 34 0
      tests/dmath/cases/log2.txt
  47. 53 0
      tests/dmath/cases/log_base.txt
  48. 69 0
      tests/dmath/cases/modf.txt
  49. 99 0
      tests/dmath/cases/pow.txt
  50. 48 0
      tests/dmath/cases/sin.txt
  51. 45 0
      tests/dmath/cases/sincos.txt
  52. 33 0
      tests/dmath/cases/sqrt.txt
  53. 54 0
      tests/dmath/cases/tan.txt
  54. 68 0
      tests/dmath/cases/trunc.txt

+ 21 - 5
.github/workflows/main.yml

@@ -24,7 +24,16 @@ jobs:
       run: |
       run: |
         python amalgamate.py
         python amalgamate.py
         cd amalgamated
         cd amalgamated
-        cl.exe /std:c11 /experimental:c11atomics /utf-8 /Ox /I. pocketpy.c main.c /link Ws2_32.lib /out:pkpy.exe
+        cl.exe /std:c11 /experimental:c11atomics /utf-8 /Ox /fp:precise /DPK_ENABLE_DETERMINISM=1 /I. pocketpy.c main.c /link Ws2_32.lib /out:pkpy.exe
+        if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
+        cl.exe /std:c11 /experimental:c11atomics /utf-8 /Ox /fp:precise /I../include pocketpy.c ../src2/test_dmath.c /link Ws2_32.lib /out:test_dmath.exe
+        if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
+        ./test_dmath.exe --cases ../tests/dmath/cases
+        if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
+        cd ..
+        ./amalgamated/pkpy.exe tests/930_dmath.py
+        if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
+        ./amalgamated/pkpy.exe tests/932_dmath_consumers.py
   build_win32:
   build_win32:
     runs-on: windows-latest
     runs-on: windows-latest
     steps:
     steps:
@@ -36,7 +45,8 @@ jobs:
       shell: bash
       shell: bash
       run: |
       run: |
         mkdir -p output/x86_64
         mkdir -p output/x86_64
-        python cmake_build.py Release -DPK_BUILD_MODULE_LZ4=ON -DPK_BUILD_MODULE_CUTE_PNG=ON -DPK_BUILD_MODULE_MSGPACK=ON
+        python cmake_build.py Release -DPK_BUILD_MODULE_LZ4=ON -DPK_BUILD_MODULE_CUTE_PNG=ON -DPK_BUILD_MODULE_MSGPACK=ON -DPK_BUILD_MATH_TESTS=ON
+        ctest --test-dir build -C Release --output-on-failure
         cp main.exe output/x86_64
         cp main.exe output/x86_64
         cp pocketpy.dll output/x86_64
         cp pocketpy.dll output/x86_64
     - uses: actions/upload-artifact@v4
     - uses: actions/upload-artifact@v4
@@ -64,10 +74,13 @@ jobs:
         bash build_g.sh
         bash build_g.sh
         bash run_tests.sh
         bash run_tests.sh
         rm -rf ./main
         rm -rf ./main
+        clang -std=c11 -Iinclude -O1 -g -fno-fast-math -ffp-contract=off -fsanitize=undefined,float-cast-overflow -fno-sanitize-recover=all src/common/dmath.c src/common/dmath_zig.c src/common/dmath_openlibm.c src2/test_dmath.c -lm -o test_dmath_sanitized
+        ./test_dmath_sanitized
     - name: Run Script Check
     - name: Run Script Check
       run: |
       run: |
         python scripts/check_pragma_once.py include
         python scripts/check_pragma_once.py include
         python scripts/check_undef.py src
         python scripts/check_undef.py src
+        python scripts/dmath/generate.py --check
     - name: Unit Test with Coverage
     - name: Unit Test with Coverage
       run: bash run_tests.sh
       run: bash run_tests.sh
     - name: Upload coverage reports to Codecov
     - name: Upload coverage reports to Codecov
@@ -80,7 +93,8 @@ jobs:
       run: |
       run: |
         python scripts/check_pragma_once.py include
         python scripts/check_pragma_once.py include
         mkdir -p output/x86_64
         mkdir -p output/x86_64
-        python cmake_build.py Release -DPK_BUILD_MODULE_LZ4=ON -DPK_BUILD_MODULE_CUTE_PNG=ON -DPK_BUILD_MODULE_MSGPACK=ON
+        python cmake_build.py Release -DPK_BUILD_MODULE_LZ4=ON -DPK_BUILD_MODULE_CUTE_PNG=ON -DPK_BUILD_MODULE_MSGPACK=ON -DPK_BUILD_MATH_TESTS=ON
+        ctest --test-dir build -C Release --output-on-failure
         python scripts/run_tests.py
         python scripts/run_tests.py
         cp main output/x86_64
         cp main output/x86_64
         cp libpocketpy.so output/x86_64
         cp libpocketpy.so output/x86_64
@@ -100,7 +114,8 @@ jobs:
           submodules: recursive
           submodules: recursive
       - name: Compile and Test
       - name: Compile and Test
         run: |
         run: |
-          python cmake_build.py Release -DPK_BUILD_MODULE_LZ4=ON -DPK_BUILD_MODULE_CUTE_PNG=ON -DPK_BUILD_MODULE_MSGPACK=ON
+          python cmake_build.py Release -DPK_BUILD_MODULE_LZ4=ON -DPK_BUILD_MODULE_CUTE_PNG=ON -DPK_BUILD_MODULE_MSGPACK=ON -DPK_BUILD_MATH_TESTS=ON
+          ctest --test-dir build -C Release --output-on-failure
           python scripts/run_tests.py
           python scripts/run_tests.py
       - name: Benchmark
       - name: Benchmark
         run: python scripts/run_tests.py benchmark
         run: python scripts/run_tests.py benchmark
@@ -187,7 +202,8 @@ jobs:
             uname -m
             uname -m
             python -c "import struct; print(8 * struct.calcsize('P'))"
             python -c "import struct; print(8 * struct.calcsize('P'))"
   
   
-            python cmake_build.py
+            python cmake_build.py Release -DPK_BUILD_MATH_TESTS=ON
+            ctest --test-dir build -C Release --output-on-failure
             python scripts/run_tests.py
             python scripts/run_tests.py
           shell: alpine.sh --root {0}
           shell: alpine.sh --root {0}
 
 

+ 70 - 0
3rd/openlibm/LICENSE.txt

@@ -0,0 +1,70 @@
+Notices for the OpenLibm source files used in pocketpy.
+
+/*
+ * ====================================================
+ * Copyright (C) 2013 Elliot Saba. All rights reserved.
+ *
+ * Developed at the University of Washington.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */

+ 131 - 0
3rd/openlibm/README.md

@@ -0,0 +1,131 @@
+# Fixed binary64 mathematical kernels
+
+pocketpy vendors the C algorithms from [OpenLibm v0.8.8](https://github.com/JuliaMath/openlibm/tree/5fe399749f9276eaa0b8403e507470da05cbbb3f),
+commit `5fe399749f9276eaa0b8403e507470da05cbbb3f`, in
+`src/common/dmath_openlibm.c`. There is no build-time download or runtime libm
+dependency for these functions.
+
+The imported files are `src/e_exp.c`, `src/s_exp2.c`, `src/e_log.c`,
+`src/e_log2.c`, `src/e_log10.c`, `src/e_pow.c`, `src/k_log.h`, and
+`src/s_scalbn.c`, plus `src/s_sin.c`, `src/s_cos.c`, `src/s_tan.c`,
+`src/s_sincos.c`, `src/k_sin.c`, `src/k_cos.c`, `src/k_tan.c`,
+`src/e_rem_pio2.c`, `src/k_rem_pio2.c`, `src/s_floor.c`, `src/s_ceil.c`, and
+`src/s_trunc.c`.
+`SHA256SUMS` records the unmodified upstream files. Copyright
+and permission notices remain in the C source and in `LICENSE.txt`; retain
+the latter with binary distributions. No OpenLibm assembly, long-double code,
+build system, or test suite is included.
+
+Local adaptations:
+
+- Prefix private functions and macros; move constants into function scope so
+  ordinary, unity, and amalgamated builds use the same algorithms.
+- Access binary64 words through `memcpy` and integer shifts, without depending
+  on the machine's byte order or violating aliasing rules.
+- Replace signed shifts and out-of-range integer conversions with defined
+  arithmetic. Bound the private `scalbn` exponent before addition.
+- Use pocketpy's correctly rounded `sqrt` and bitwise `fabs`/`copysign` helpers.
+- Canonicalize every NaN result to `0x7ff8000000000000`. Preserve signed zeros.
+- Rely on the build configuration to disable FP contraction; no local FP pragmas.
+- Implement `dmath_exp10(x)` through the fixed `pow(10, x)` kernel and
+  `dmath_log_base(x, base)` through the fixed natural logarithm kernels.
+- Specialize large-angle reduction to binary64 (upstream `prec = 1`), retaining
+  the first 66 words of the `2/pi` table and the adaptive recomputation steps.
+  The full finite binary64 range, including `DBL_MAX`, is supported.
+- Reuse the private `scalbn` and a bit-mask adaptation of `floor`; neither
+  helper calls the host libm. Public `dmath_floor` shares the same kernel.
+- Share the sine/cosine kernels and one reduction in `dmath_sincos`, using the
+  same tiny-input cutoffs as the separate functions so results agree bitwise.
+  Tangent uses its dedicated polynomial and compensated reciprocal kernel.
+- Implement `ceil`/`floor`/`trunc` using the upstream exponent/mask algorithms
+  with one unsigned 64-bit word in place of two 32-bit words. These kernels
+  never cast the floating value to an integer and omit upstream operations
+  used solely to raise the inexact flag. Finite results are exact across the
+  complete binary64 range and independent of the host rounding mode.
+
+The coefficients, table entries, reduction steps, and floating-point operation
+order are pinned. Upstream updates must be reviewed as numerical behavior
+changes; do not regenerate expected results just to make a failing test pass.
+
+## Determinism contract
+
+Given identical binary64 input bits, finite results (including signed zeros)
+have identical bits on supported builds with IEEE 754 binary64 arithmetic, round-to-nearest-even,
+and gradual underflow. The embedding application must leave FTZ/DAZ disabled
+and must not change the thread's rounding mode while evaluating Python code.
+The library does not change the host floating-point environment. Hardware
+exception traps must be disabled. NaNs are compared by classification and
+infinities by classification/sign; nonfinite bit patterns, `errno`, NaN payload
+propagation, and FP exception flags are not part of the contract. The OpenLibm
+wrappers currently canonicalize NaNs as an implementation detail.
+
+Use GCC/Clang with `-fno-fast-math -ffp-contract=off`, or MSVC with `/fp:precise`.
+The deterministic CMake configuration supplies these options. On 32-bit x86,
+use SSE2 and `-mfpmath=sse`; x87 excess precision is rejected. The kernels also
+reject detectable fast-math/finite-only builds and non-binary64 formats.
+Custom/amalgamated builds must obey the same contract. Architecture-specific
+libm calls, FMA variants, and CPU dispatch must not be added to this layer.
+The build flag `-ffp-contract=off` is required for GCC/Clang. Source files do
+not adapt compiler options locally. There is no portable preprocessor macro
+that detects contraction mode; hardware FMA availability is not such a check.
+
+Determinism takes priority over matching a particular CPython platform's libm.
+OpenLibm's documented approximation error is below one ulp for `exp`/`log` and
+below 0.503 ulp for normal `exp2` results. This is not a claim of correct rounding
+for all inputs or a universal one-ulp bound on `pow`; its small-integer multiply
+shortcuts can accumulate rounding error.
+The trigonometric kernels are described upstream as nearly rounded; this does
+not promise correct rounding for every input. The accuracy vectors test them
+against independently computed references with a one-ulp allowance.
+
+## Python behavior
+
+`math.exp`, `math.log`, `math.log2`, `math.log10`,
+`math.pow`, and floating `**` share this layer. Consumers such as `cmath`,
+easing, and color conversion inherit the new kernels.
+`math.sin`, `math.cos`, `math.tan`, and internal `dmath_sincos` also use this
+layer. Vector/matrix rotations retain the combined sine/cosine entry point.
+`math.ceil`, `math.floor`, and `math.trunc` use the fixed rounding kernels;
+floating `//` and `divmod` also inherit `dmath_floor`.
+
+The C functions return IEEE values, also exposed by the Python math wrappers:
+overflow returns signed infinity, underflow returns a subnormal or signed zero,
+and invalid real domains return canonical NaN. Logarithms of zero return
+negative infinity; zero to a negative floating power returns signed infinity.
+No arithmetic exception type or new Python math API is introduced. This is an
+intentional difference from CPython's domain/overflow exception policy.
+
+The C rounding functions preserve signed zeros and infinities and canonicalize
+NaNs. Python `math.ceil`/`floor`/`trunc` return an `int` when the result fits the
+signed 64-bit range. Results outside that range remain integral `float` values;
+NaNs and infinities also remain floats instead of raising an exception or
+undergoing an undefined integer conversion. Integer inputs are returned exactly,
+without a round trip through double. Zero results at the Python level remain
+integer zero. This differs from CPython's arbitrary-precision integer results
+and its exceptions for nonfinite rounding inputs.
+
+Integer `**` preserves its fixed-width result type and now uses defined
+modulo-2**64 arithmetic instead of C signed-overflow UB. The existing
+`ZeroDivisionError` for integer zero to a negative integer power is retained.
+Existing pocketpy limitations remain: no arbitrary-precision integers, no
+automatic complex promotion for negative fractional real powers (`**` returns
+NaN), and the existing numeric conversion protocol. The audit and tests of the
+remaining dmath functions are documented in `tests/dmath/README.md`.
+
+## Validation
+
+Configure with `-DPK_BUILD_MATH_TESTS=ON`, build, then run
+`ctest --test-dir <build-directory> -C Release --output-on-failure`.
+
+The new suite covers all 31 public dmath functions in separate groups, with
+one readable case file per function under `tests/dmath/cases/`. It replaces
+the previous vector headers and shared fingerprints. CTest also forces the
+software sqrt path on hardware-sqrt hosts. `tests/930_dmath.py` checks Python
+bindings using the same finite output bits and nonfinite classification/sign
+expectations; `tests/932_dmath_consumers.py` checks operators and other consumers.
+
+Independent Decimal/Fraction references, frozen output bits and per-function
+random sweeps are distinct checks. See `tests/dmath/README.md` for the case
+categories, numerical contract, audit findings, commands and baseline review
+process. Check references with `python scripts/dmath/generate.py --check`;
+this never updates frozen expectations from implementation outputs.

+ 20 - 0
3rd/openlibm/SHA256SUMS

@@ -0,0 +1,20 @@
+870c86c084296ef8838377c53ffc32cf0131e559e5188d400c0c2199b57670ca  src/e_exp.c
+c517560ccaed663f9630598aa3a574cc4bea99e45b701691c014ef60424d2b7a  src/s_exp2.c
+8996b789a4cbbcef7cf7d568c1be558ce9110900a40ca6c46fb4ed46c343cafd  src/e_log.c
+bda62faa51891879040614ea0762d335e9f2c96397cefcd5d8268b3bee5e3acb  src/e_log2.c
+96346b524dda8bcecd4ee690577efee9b4a5e4fca83b00e7adf2eeb2430c0989  src/e_log10.c
+13c580f60a6e2f48ef36ff1e9c46cdd394c9cd9c0fceb18f2526404fcb949ec7  src/e_pow.c
+739f9832a62c487c2b511ab6dca4a728ecc1cfec2bf896cc828fbd964f77ca13  src/k_log.h
+f528db57150cb0457e3ab9ddb24c6b38e33fa06814cf2f9005653f354eb216d1  src/s_scalbn.c
+c6a867fea444a062615ea521c6f307531baf35d03b039615cb7fcdaf3775e6ee  src/s_sin.c
+e3e86b502f3629cd6cb14f83585266b43e2595646ad62fbbbebd0a349c34458c  src/s_cos.c
+e2f7ff6a0ae13c287d53b401d1c395936701f28ea8a368cd1e8ab65103414ee7  src/s_tan.c
+3a872d76c10007b8b2646a18a282fc7c9af3e634a1bb23866c7152827d44de7d  src/s_sincos.c
+1c9ab096c98e3f589aeb7a14619fb82e4b63e82f6ee9be8349af8c96de2a3e7a  src/k_sin.c
+3d7fce5fa51a8469bf69ff3757109986872f889b73efecd2a9787f0584797cb3  src/k_cos.c
+064042ee5d51dd4aa7ecfb21ea20e941565a21475d156a80ecacb1db0aa3771a  src/k_tan.c
+70218a9f96dde3f3045521600330d9c46040212c617a1bfd539cc1e766e6660b  src/e_rem_pio2.c
+ade789bf2edce95bcbe7582caf9978c4b0759891c1f5e4fca9278bd4715de2a8  src/k_rem_pio2.c
+27e086e84c6f5264530025d72dca9fdbee455a0696c234f6fceedb97f021b9d1  src/s_floor.c
+7cf460d28b750b22e36fcf493a6ab0b7ea227ddc835d07308c3e8535592eb889  src/s_ceil.c
+26a7f3f531b95c79aee1c94cd47acb93aa0963332cf20402d99f6df23438693e  src/s_trunc.c

+ 25 - 1
CMakeLists.txt

@@ -19,7 +19,7 @@ if(MSVC)
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /utf-8 /jumptablerdata")
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /utf-8 /jumptablerdata")
     add_compile_options(/wd4267 /wd4244 /wd4146 /wd4819 /experimental:c11atomics)
     add_compile_options(/wd4267 /wd4244 /wd4146 /wd4819 /experimental:c11atomics)
     if(PK_ENABLE_DETERMINISM)
     if(PK_ENABLE_DETERMINISM)
-        add_compile_options(/fp:strict)
+        add_compile_options(/fp:precise)
     endif()
     endif()
 
 
     if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
     if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
@@ -201,3 +201,27 @@ endif()
 if(PK_ENABLE_MIMALLOC)
 if(PK_ENABLE_MIMALLOC)
     target_link_libraries(${PROJECT_NAME} mimalloc-static)
     target_link_libraries(${PROJECT_NAME} mimalloc-static)
 endif()
 endif()
+
+if(PK_BUILD_MATH_TESTS)
+    enable_testing()
+    # Compile the kernels directly so the test also works with DLL builds that
+    # intentionally do not export the internal dmath symbols.
+    set(DMATH_TEST_SOURCES src2/test_dmath.c src/common/dmath.c
+                           src/common/dmath_zig.c src/common/dmath_openlibm.c)
+    add_executable(test_dmath ${DMATH_TEST_SOURCES})
+    add_executable(test_dmath_soft_sqrt ${DMATH_TEST_SOURCES})
+    target_compile_definitions(test_dmath_soft_sqrt PRIVATE PK_DMATH_SOFT_SQRT=1)
+    if(UNIX)
+        target_link_libraries(test_dmath m)
+        target_link_libraries(test_dmath_soft_sqrt m)
+    endif()
+    set(DMATH_CASE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/tests/dmath/cases)
+    foreach(function isfinite isinf isnan isnormal fabs copysign fmin fmax
+                     ceil floor trunc modf fmod sqrt cbrt exp exp2 exp10 pow
+                     log log2 log10 log_base sin cos tan sincos asin acos atan atan2)
+        add_test(NAME dmath.${function}
+                 COMMAND test_dmath --cases ${DMATH_CASE_DIR} ${function})
+    endforeach()
+    add_test(NAME dmath.sqrt_software
+             COMMAND test_dmath_soft_sqrt --cases ${DMATH_CASE_DIR} sqrt)
+endif()

+ 1 - 0
CMakeOptions.txt

@@ -13,6 +13,7 @@ option(PK_ENABLE_DETERMINISM "" ON)
 option(PK_ENABLE_WATCHDOG "" OFF)
 option(PK_ENABLE_WATCHDOG "" OFF)
 option(PK_ENABLE_CUSTOM_SNAME "" OFF)
 option(PK_ENABLE_CUSTOM_SNAME "" OFF)
 option(PK_ENABLE_MIMALLOC "" OFF)
 option(PK_ENABLE_MIMALLOC "" OFF)
+option(PK_BUILD_MATH_TESTS "Build deterministic binary64 kernel tests" OFF)
 
 
 # modules
 # modules
 option(PK_BUILD_MODULE_LZ4 "" OFF)
 option(PK_BUILD_MODULE_LZ4 "" OFF)

+ 5 - 1
amalgamate.py

@@ -166,10 +166,14 @@ def checked_sh(cmd):
 	assert ok == 0, f"command failed: {cmd}"
 	assert ok == 0, f"command failed: {cmd}"
 
 
 if sys.platform in ['linux', 'darwin']:
 if sys.platform in ['linux', 'darwin']:
-	common_flags = "-O1 --std=c11 -lm -ldl -lpthread -Iamalgamated"
+	common_flags = "-O1 --std=c11 -fno-fast-math -ffp-contract=off -DPK_ENABLE_DETERMINISM=1 -lm -ldl -lpthread -Iamalgamated"
 	checked_sh(f"gcc -o main amalgamated/pocketpy.c src2/example.c {common_flags}")
 	checked_sh(f"gcc -o main amalgamated/pocketpy.c src2/example.c {common_flags}")
 	checked_sh("./main && rm -f ./main")
 	checked_sh("./main && rm -f ./main")
 	checked_sh(f"gcc -o main amalgamated/pocketpy.c amalgamated/main.c {common_flags}")
 	checked_sh(f"gcc -o main amalgamated/pocketpy.c amalgamated/main.c {common_flags}")
+	checked_sh(f"gcc -o amalgamated/test_dmath amalgamated/pocketpy.c src2/test_dmath.c -Iinclude {common_flags}")
+	checked_sh("./amalgamated/test_dmath")
+	checked_sh("./main tests/930_dmath.py")
+	checked_sh("./main tests/932_dmath_consumers.py")
 
 
 
 
 print("amalgamated/pocketpy.h")
 print("amalgamated/pocketpy.h")

+ 1 - 1
build_g.sh

@@ -4,7 +4,7 @@ set -e
 
 
 SRC=$(find src/ -name "*.c")
 SRC=$(find src/ -name "*.c")
 
 
-FLAGS="-std=c11 -lm -ldl -lpthread -Iinclude -O0 -Wfatal-errors -g -DDEBUG -DPK_ENABLE_OS=1"
+FLAGS="-std=c11 -lm -ldl -lpthread -Iinclude -O0 -Wfatal-errors -g -DDEBUG -DPK_ENABLE_OS=1 -DPK_ENABLE_DETERMINISM=1 -fno-fast-math -ffp-contract=off"
 
 
 SANITIZE_FLAGS="-fsanitize=address,leak,undefined -fno-sanitize=function"
 SANITIZE_FLAGS="-fsanitize=address,leak,undefined -fno-sanitize=function"
 
 

+ 43 - 5
include/pocketpy/common/dmath.h

@@ -1,7 +1,37 @@
 #pragma once
 #pragma once
 
 
-#define DMATH_INFINITY ((float)((1e+300 * 1e+300)))
-#define DMATH_NAN ((float)(DMATH_INFINITY * 0.0F))
+#include <float.h>
+#include <stdint.h>
+#include <string.h>
+
+_Static_assert(sizeof(double) == 8 && FLT_RADIX == 2 && DBL_MANT_DIG == 53 &&
+                   DBL_MAX_EXP == 1024 && DBL_MIN_EXP == -1021,
+               "dmath requires IEEE 754 binary64");
+#if defined(FLT_EVAL_METHOD) && FLT_EVAL_METHOD != 0
+#error "dmath requires binary64 evaluation; use SSE2 (-msse2 -mfpmath=sse) on x86"
+#endif
+#if defined(__FAST_MATH__) || (defined(__FINITE_MATH_ONLY__) && __FINITE_MATH_ONLY__ > 0) || \
+    defined(_M_FP_FAST)
+#error "dmath cannot be compiled with fast-math or finite-math-only"
+#endif
+
+static inline uint64_t pk_dmath_bits(double x) {
+    uint64_t u;
+    memcpy(&u, &x, sizeof(u));
+    return u;
+}
+
+static inline double pk_dmath_from_bits(uint64_t u) {
+    double x;
+    memcpy(&x, &u, sizeof(x));
+    return x;
+}
+
+// Construct constants without arithmetic: directed rounding can turn an
+// overflowing product into a finite number, making the old infinity * 0 zero.
+// The chosen NaN encoding is an implementation detail, not a result contract.
+#define DMATH_INFINITY (pk_dmath_from_bits(UINT64_C(0x7ff0000000000000)))
+#define DMATH_NAN (pk_dmath_from_bits(UINT64_C(0x7ff8000000000000)))
 #define DMATH_PI 3.1415926535897932384
 #define DMATH_PI 3.1415926535897932384
 #define DMATH_E 2.7182818284590452354
 #define DMATH_E 2.7182818284590452354
 #define DMATH_DEG2RAD 0.017453292519943295
 #define DMATH_DEG2RAD 0.017453292519943295
@@ -9,10 +39,13 @@
 #define DMATH_EPSILON 1e-10
 #define DMATH_EPSILON 1e-10
 #define DMATH_LOG2_E 1.4426950408889634
 #define DMATH_LOG2_E 1.4426950408889634
 
 
-// Fixed OpenLibm binary64 kernels. Require round-to-nearest-even, gradual
+// All dmath functions require round-to-nearest-even, gradual
 // underflow (FTZ/DAZ disabled), and no fast-math or excess intermediate precision.
 // underflow (FTZ/DAZ disabled), and no fast-math or excess intermediate precision.
-// These return IEEE values (including canonical quiet NaN 0x7ff8000000000000);
-// Python exceptions belong to the bindings. See third-party/openlibm/README.md.
+// Determinism requires identical finite result bits, including signed zero.
+// NaNs are checked by classification, infinities by classification and sign;
+// nonfinite bit patterns and NaN payload/signaling propagation are not promised.
+// Classification functions inspect bits without floating-point arithmetic.
+// Python exceptions belong to the bindings. See 3rd/openlibm/README.md.
 double dmath_exp2(double x);
 double dmath_exp2(double x);
 double dmath_log2(double x);
 double dmath_log2(double x);
 
 
@@ -20,6 +53,7 @@ double dmath_exp(double x);
 double dmath_exp10(double x);
 double dmath_exp10(double x);
 double dmath_log(double x);
 double dmath_log(double x);
 double dmath_log10(double x);
 double dmath_log10(double x);
+double dmath_log_base(double x, double base);
 double dmath_pow(double base, double exp);
 double dmath_pow(double base, double exp);
 double dmath_sqrt(double x);
 double dmath_sqrt(double x);
 double dmath_cbrt(double x);
 double dmath_cbrt(double x);
@@ -42,10 +76,14 @@ double dmath_fmod(double x, double y);
 double dmath_copysign(double x, double y);
 double dmath_copysign(double x, double y);
 
 
 double dmath_fabs(double x);
 double dmath_fabs(double x);
+// Fixed OpenLibm binary64 rounding: preserve signed zero and infinity,
+// canonicalize NaNs, and return exact integral doubles without integer casts.
 double dmath_ceil(double x);
 double dmath_ceil(double x);
 double dmath_floor(double x);
 double dmath_floor(double x);
 double dmath_trunc(double x);
 double dmath_trunc(double x);
 double dmath_modf(double x, double* intpart);
 double dmath_modf(double x, double* intpart);
 
 
+// Ignore a single NaN; two NaNs produce NaN. For a zero tie,
+// fmin returns -0 if either operand is -0; fmax returns +0 if either is +0.
 double dmath_fmin(double x, double y);
 double dmath_fmin(double x, double y);
 double dmath_fmax(double x, double y);
 double dmath_fmax(double x, double y);

+ 343 - 0
scripts/dmath/cases.py

@@ -0,0 +1,343 @@
+"""The reviewed test design: one case group per public dmath function.
+
+Hexadecimal inputs name exact binary64 values, not approximate decimal inputs.
+Every boundary expansion retains its purpose in the emitted case name.
+These groups were designed afresh; no legacy vectors or fingerprints are used.
+"""
+
+from dataclasses import dataclass
+from oracle import bits, value, SIGN, INF
+
+
+@dataclass(frozen=True)
+class Case:
+    name: str
+    x: int
+    y: int = 0
+
+
+def word(x):
+    return bits(float.fromhex(x)) if isinstance(x, str) else bits(float(x))
+
+
+def c(name, x, y=0):
+    return Case(name, word(x), word(y))
+
+
+def edge(name, x, both_signs=False):
+    u = word(x)
+    assert 0 < u < INF
+    rows = [Case(name + suffix, u + offset) for suffix, offset in
+            [('_below', -1), ('_at', 0), ('_above', 1)]]
+    if both_signs:
+        rows += [Case('negative_' + r.name, r.x | SIGN) for r in rows]
+    return rows
+
+
+def special():
+    return [
+        Case('positive_zero', 0), Case('negative_zero', SIGN),
+        Case('least_subnormal', 1), Case('negative_least_subnormal', SIGN | 1),
+        Case('third_subnormal', 3), Case('negative_third_subnormal', SIGN | 3),
+        Case('largest_subnormal', 0x000FFFFFFFFFFFFF),
+        Case('negative_largest_subnormal', 0x800FFFFFFFFFFFFF),
+        Case('least_normal', 0x0010000000000000),
+        Case('negative_least_normal', 0x8010000000000000),
+        Case('largest_finite', 0x7FEFFFFFFFFFFFFF),
+        Case('negative_largest_finite', 0xFFEFFFFFFFFFFFFF),
+        Case('positive_infinity', INF), Case('negative_infinity', INF | SIGN),
+        Case('quiet_nan_payload', 0x7FF8ABCDEF135790),
+        Case('negative_quiet_nan_payload', 0xFFF8ABCDEF135790),
+        Case('signaling_nan_payload', 0x7FF0000000010248),
+        Case('negative_signaling_nan_payload', 0xFFF0000000010248),
+    ]
+
+
+def cases_isfinite():
+    return special() + [c('ordinary_positive', '0x1.abc123p+37'),
+                        c('ordinary_negative', '-0x1.2468p-137')]
+
+
+def cases_isinf():
+    return special() + [Case('exponent_below_infinity', 0x7FE0000000000000),
+                        Case('first_nan_encoding', INF + 1)]
+
+
+def cases_isnan():
+    return special() + [Case('all_fraction_bits_set', 0x7FFFFFFFFFFFFFFF),
+                        Case('negative_all_bits_set', 0xFFFFFFFFFFFFFFFF)]
+
+
+def cases_isnormal():
+    return special() + edge('normal_transition', '0x1p-1022', True)
+
+
+def cases_fabs():
+    return special() + [c('negative_fraction', '-0x1.96p-4'),
+                        c('negative_large_integral', '-0x1.23456789abcdep+89')]
+
+
+def cases_copysign():
+    rows = []
+    for r in special() + [c('ordinary', '0x1.b38p+6')]:
+        rows += [Case(r.name + '_positive_sign', r.x, word('0x1p-81')),
+                 Case(r.name + '_negative_sign', r.x, word('-0x1p+81'))]
+    rows += [Case('sign_from_negative_nan', word(7.625), 0xFFF0000000010248),
+             Case('sign_from_negative_zero', word(7.625), SIGN),
+             Case('sign_from_positive_nan', word(-7.625), 0x7FF8ABCDEF135790)]
+    return rows
+
+
+def ordering_cases():
+    pairs = [(0, SIGN), (SIGN, 0), (SIGN, SIGN), (0, 0),
+             (word(-7.625), word(3.1875)), (1, 3),
+             (INF, word(11.125)), (INF | SIGN, word(-11.125))]
+    rows = [Case('ordered_pair_' + str(i), a, b) for i, (a, b) in enumerate(pairs)]
+    for nan in special()[-4:]:
+        rows += [Case(nan.name + '_left', nan.x, word(13.25)),
+                 Case(nan.name + '_right', word(13.25), nan.x),
+                 Case(nan.name + '_both', nan.x, 0xFFF8ABCDEF135790)]
+    return rows
+
+
+def cases_fmin():
+    return ordering_cases() + [c('equal_negative_numbers', -19.875, -19.875)]
+
+
+def cases_fmax():
+    return ordering_cases() + [c('equal_positive_numbers', 19.875, 19.875)]
+
+
+def rounding_boundaries():
+    rows = special()
+    for label, x in [('unit', '0x1p+0'), ('half', '0x1p-1'),
+                     ('word_split', '0x1p+20'), ('signed32', '0x1p+31'),
+                     ('last_fractional_binade', '0x1p+51'),
+                     ('integral_binade', '0x1p+52'), ('signed64', '0x1p+63')]:
+        rows += edge(label, x, True)
+    return rows
+
+
+def cases_ceil():
+    return rounding_boundaries() + [c('up_from_positive_fraction', 23.0625),
+                                    c('up_from_negative_fraction', -23.0625)]
+
+
+def cases_floor():
+    return rounding_boundaries() + [c('down_from_positive_fraction', 23.9375),
+                                    c('down_from_negative_fraction', -23.9375)]
+
+
+def cases_trunc():
+    return rounding_boundaries() + [c('drop_positive_fraction', 37.6875),
+                                    c('drop_negative_fraction', -37.6875)]
+
+
+def cases_modf():
+    return rounding_boundaries() + [c('split_positive', 129.8125),
+                                    c('split_negative', -129.8125),
+                                    c('exact_negative_integer', -129)]
+
+
+def cases_fmod():
+    rows = [c('positive_remainder', 53.75, 7.5), c('negative_remainder', -53.75, 7.5),
+            c('negative_divisor', 53.75, -7.5), c('both_negative', -53.75, -7.5),
+            c('positive_exact_multiple', 52.5, 7.5),
+            c('negative_exact_multiple', -52.5, 7.5),
+            c('quotient_exceeds_double', '0x1.abcdefp+900', '0x1.7p-901'),
+            c('subnormal_remainder', '0x1.0000000000001p-1022', '0x1p-1022'),
+            Case('subnormal_division', 29, 7), Case('negative_subnormal_division', SIGN | 29, 7)]
+    for r in special():
+        rows += [Case(r.name + '_dividend', r.x, word(7.5)),
+                 Case(r.name + '_divisor', word(-53.75), r.x)]
+    return rows
+
+
+def cases_sqrt():
+    return (special() + [c('exact_square', 206.640625), c('irrational', 13.625),
+                         c('wide_significand', '0x1.a5c739b18426fp+409')]
+            + edge('square_neighbor', '0x1.9d48p+7')
+            + edge('normal_subnormal_transition', '0x1p-1022'))
+
+
+def cases_cbrt():
+    rows = special() + [c('exact_positive_cube', 155.287109375),
+                        c('exact_negative_cube', -155.287109375),
+                        c('irrational_positive', 19.375), c('irrational_negative', -19.375)]
+    for rem in range(3):
+        rows += edge('exponent_class_' + str(rem), '0x1.73p+' + str(600 + rem), True)
+    return rows
+
+
+def cases_exp():
+    rows = special() + [c('moderate_positive', 6.3125), c('moderate_negative', -6.3125),
+                        c('large_finite_result', 708.375), c('subnormal_result', -738.625)]
+    for name, x in [('tiny_shortcut', '0x1p-28'), ('first_reduction', '0x1.62e43p-2'),
+                    ('second_reduction', '0x1.0a2b2p+0'),
+                    ('overflow_boundary', '0x1.62e42fefa39efp+9')]:
+        rows += edge(name, x, True)
+    # The last nonzero result lies at this negative magnitude.
+    rows += [Case('underflow_' + r.name, r.x | SIGN)
+             for r in edge('threshold', '0x1.74910d52d3051p+9')]
+    return rows
+
+
+def cases_exp2():
+    rows = special() + [c('fractional_positive', 12.3125), c('fractional_negative', -12.3125),
+                        c('exact_normal_power', -847), c('subnormal_power', -1053)]
+    for n in (9, 67, 143, 219):
+        rows += edge('table_midpoint_' + str(n), value(word((n + 0.5) / 256)))
+    rows += edge('overflow', '0x1p+10')
+    rows += [Case('underflow_' + r.name, r.x | SIGN)
+             for r in edge('tie', 1075)]
+    return rows
+
+
+def cases_exp10():
+    return (special() + [c('exact_positive_power', 17), c('negative_power', -17),
+                         c('fractional_positive', 4.1875), c('fractional_negative', -4.1875),
+                         c('subnormal_result', -319.75)]
+            + edge('overflow', '0x1.34413509f79ffp+8'))
+
+
+def log_boundaries():
+    return (special() + edge('near_one', 1) + edge('normalize', '0x1.6a09ep+0')
+            + [c('less_than_one', 0.171875), c('greater_than_one', 23.5625)])
+
+
+def cases_log():
+    return log_boundaries() + [c('wide_exponent', '0x1.a9bcdef012345p+723')]
+
+
+def cases_log2():
+    return log_boundaries() + [c('exact_binary_power', '0x1p-817'),
+                               c('exact_subnormal_power', '0x1p-1053')]
+
+
+def cases_log10():
+    return log_boundaries() + [c('decimal_power', 10000000),
+                               c('small_decimal', 0.00000003125)]
+
+
+def cases_log_base():
+    rows = [c('base_above_one', 19.375, 3.25), c('base_below_one', 19.375, 0.3125),
+            c('argument_below_one', 0.3125, 3.25), c('equal_base_and_argument', 3.25, 3.25),
+            c('zero_result_sign', 1, 0.3125), c('base_one_positive', 19.375, 1),
+            c('base_one_negative', 0.3125, 1), c('both_one', 1, 1),
+            c('near_one_pair', '0x1.0000000000003p+0', '0x1.0000000000007p+0')]
+    for r in special():
+        rows += [Case(r.name + '_argument', r.x, word(3.25)),
+                 Case(r.name + '_base', word(19.375), r.x)]
+    rows += [Case('both_infinite', INF, INF), Case('both_zero', 0, 0)]
+    return rows
+
+
+def cases_pow():
+    rows = [c('positive_fractional', 3.3125, 2.1875),
+            c('negative_odd_integer', -3.3125, 7), c('negative_even_integer', -3.3125, 6),
+            c('negative_reciprocal', -3.3125, -7), c('negative_fractional_domain', -3.3125, 2.1875),
+            c('square_shortcut', '0x1.abcdef1234567p+5', 2),
+            c('cube_shortcut', '0x1.abcdef1234567p+5', 3),
+            c('fourth_power_shortcut', '0x1.abcdef1234567p+5', 4),
+            c('sqrt_shortcut', 23.5625, 0.5), c('reciprocal_shortcut', 23.5625, -1),
+            c('near_one_large_positive', '0x1.0000000000003p+0', '0x1p+49'),
+            c('near_one_large_negative', '0x1.ffffffffffffbp-1', '-0x1p+49'),
+            c('finite_overflow', 7.625, 4096), c('finite_underflow', 7.625, -4096),
+            c('negative_odd_overflow', -7.625, 4097), c('negative_odd_underflow', -7.625, -4097),
+            c('largest_odd_exponent', -1, '0x1.fffffffffffffp+52'),
+            c('first_even_only_binade', -1, '0x1p+53')]
+    for r in special():
+        rows += [Case(r.name + '_odd_power', r.x, word(7)),
+                 Case(r.name + '_negative_odd_power', r.x, word(-7)),
+                 Case(r.name + '_zero_power', r.x, 0),
+                 Case(r.name + '_exponent', word(3.3125), r.x)]
+    rows += [Case('one_to_nan', word(1), 0xFFF0000000010248),
+             Case('negative_one_to_infinity', word(-1), INF),
+             Case('negative_zero_fractional_pole', SIGN, word(-0.25))]
+    return rows
+
+
+def angle_cases():
+    rows = special() + [c('small_positive_angle', 0.34375), c('small_negative_angle', -0.34375),
+                        c('moderate_positive_angle', 43.8125), c('moderate_negative_angle', -43.8125),
+                        c('large_reduction', '0x1.a5c739b18426fp+41'),
+                        c('very_large_reduction', '0x1.73b4a82cf19dep+811')]
+    rows += edge('quarter_turn_kernel', '0x1.921fb54442d18p-1', True)
+    rows += edge('medium_reduction_cutoff', '0x1.921fbp+20', True)
+    return rows
+
+
+def cases_sin():
+    return angle_cases() + edge('tiny_cutoff', '0x1p-26', True)
+
+
+def cases_cos():
+    return angle_cases() + edge('tiny_cutoff', '0x1.6a09ep-27', True)
+
+
+def cases_tan():
+    return (angle_cases() + edge('reciprocal_pole', '0x1.2d97c7f3321d2p+2', True)
+            + edge('kernel_transform', '0x1.59428p-1', True))
+
+
+def cases_sincos():
+    return angle_cases() + [c('second_quadrant', 2.3125), c('third_quadrant', 4.1875),
+                            c('fourth_quadrant', 5.9375)]
+
+
+def cases_asin():
+    return (special() + edge('domain_endpoint', 1, True) + edge('half_interval', 0.5, True)
+            + edge('near_endpoint_formula', '0x1.f3333p-1', True)
+            + [c('interior_positive', 0.71875), c('interior_negative', -0.71875)])
+
+
+def cases_acos():
+    return (special() + edge('domain_endpoint', 1, True) + edge('half_interval', 0.5, True)
+            + edge('tiny_cutoff', '0x1p-57', True)
+            + [c('interior_positive', 0.28125), c('interior_negative', -0.28125)])
+
+
+def cases_atan():
+    rows = special() + [c('ordinary_positive', 9.3125), c('ordinary_negative', -9.3125)]
+    for label, x in [('tiny_cutoff', '0x1p-27'), ('first_interval', 0.4375),
+                     ('second_interval', 0.6875), ('third_interval', 1.1875),
+                     ('reciprocal_interval', 2.4375), ('asymptote', '0x1p+66')]:
+        rows += edge(label, x, True)
+    return rows
+
+
+def cases_atan2():
+    rows = []
+    for i, (y, x) in enumerate([(5.8125, 0.21875), (5.8125, -0.21875),
+                                (-5.8125, 0.21875), (-5.8125, -0.21875)]):
+        rows.append(c('quadrant_' + str(i + 1), y, x))
+    for y in [0, SIGN, INF, INF | SIGN]:
+        for x in [0, SIGN, INF, INF | SIGN]:
+            rows.append(Case('axes_%016x_%016x' % (y, x), y, x))
+    for r in special():
+        rows += [Case(r.name + '_ordinate', r.x, word(-5.8125)),
+                 Case(r.name + '_abscissa', word(-5.8125), r.x)]
+    rows += [c('tiny_ratio', '0x1p-1000', '0x1p+900'),
+             c('huge_ratio', '0x1p+900', '0x1p-1000'),
+             c('tiny_ratio_negative_x', '0x1p-1000', '-0x1p+900'),
+             c('unit_abscissa_shortcut', 1.8125, 1)]
+    return rows
+
+
+# Declaration order is the category order in the test reports.
+GROUPS = {
+    'classification': ['isfinite', 'isinf', 'isnan', 'isnormal'],
+    'sign_and_order': ['fabs', 'copysign', 'fmin', 'fmax'],
+    'rounding_and_remainder': ['ceil', 'floor', 'trunc', 'modf', 'fmod'],
+    'roots': ['sqrt', 'cbrt'],
+    'exponentials': ['exp', 'exp2', 'exp10', 'pow'],
+    'logarithms': ['log', 'log2', 'log10', 'log_base'],
+    'trigonometry': ['sin', 'cos', 'tan', 'sincos'],
+    'inverse_trigonometry': ['asin', 'acos', 'atan', 'atan2'],
+}
+
+# Tolerances apply only to the independent accuracy oracle, never to the frozen
+# implementation results. They are case-suite budgets, not universal bounds.
+ULPS = {name: 0 for name in sum(list(GROUPS.values())[:4], [])}
+ULPS.update(cbrt=1, exp=1, exp2=1, exp10=2, pow=2, log=1, log2=1, log10=1,
+            log_base=3, sin=1, cos=1, tan=1, sincos=1, asin=1, acos=1, atan=1, atan2=2)

+ 104 - 0
scripts/dmath/generate.py

@@ -0,0 +1,104 @@
+"""Generate/check per-function cases from the independent oracle.
+
+Run: python scripts/dmath/generate.py [--check]
+Existing frozen output bits are preserved only if the case name and inputs
+match. New cases are emitted as PENDING and fail normal test runs until their
+results have been reviewed on independent compiler builds. This script never
+calls the implementation or silently blesses changed results.
+"""
+
+import argparse
+from decimal import localcontext, InvalidOperation, DivisionByZero, Overflow
+from pathlib import Path
+import re
+import cases
+from oracle import reference, value, INF, MASK, SIGN
+
+ROOT = Path(__file__).resolve().parents[2]
+DEST = ROOT / 'tests/dmath/cases'
+
+
+def result_text(u):
+    magnitude = u & MASK
+    if magnitude > INF:
+        return 'nan'
+    if magnitude == INF:
+        return '-inf' if u & SIGN else '+inf'
+    return '%016x' % u
+
+
+def old_results(path):
+    rows, sweep = {}, 'PENDING'
+    if path.exists():
+        for line in path.read_text().splitlines():
+            if line.startswith('# sweep '):
+                sweep = line.split()[2]
+            elif line and not line.startswith('#'):
+                fields = line.split()
+                rows[tuple(fields[:3])] = [result_text(int(x, 16)) if len(x) == 16 else x
+                                           for x in fields[3:5]]
+    return rows, sweep
+
+
+def render(name, rows, path):
+    existing, sweep = old_results(path)
+    text = ['# dmath_' + name,
+            '# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.',
+            '# Frozen bits and sweep require review; generation never recalibrates them.',
+            '# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.',
+            '# sweep ' + sweep,
+            '# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp']
+    for row in rows:
+        refs = []
+        for precision in (430, 570):
+            with localcontext() as context:
+                context.prec = precision
+                for trap in (InvalidOperation, DivisionByZero, Overflow):
+                    context.traps[trap] = False
+                refs.append(reference(name, row.x, row.y))
+        if refs[0] != refs[1]:
+            raise RuntimeError('reference did not converge: ' + name + '/' + row.name)
+        outputs = refs[0] + (0,) * (2 - len(refs[0]))
+        key = (row.name, '%016x' % row.x, '%016x' % row.y)
+        frozen = existing.get(key, ['PENDING', 'PENDING'])
+        # Human-readable inputs stay next to their exact binary representations.
+        comment = ' # x=' + value(row.x).hex() + ' y=' + value(row.y).hex()
+        fields = [*key, *frozen, *[result_text(r) for r in outputs], str(cases.ULPS[name])]
+        text.append(' '.join(fields) + comment)
+    return '\n'.join(text) + '\n'
+
+
+def main():
+    parser = argparse.ArgumentParser(description=__doc__)
+    parser.add_argument('--check', action='store_true')
+    args = parser.parse_args()
+    exported = set(re.findall(r'^(?:double|int|void) dmath_(\w+)\(',
+                             (ROOT / 'include/pocketpy/common/dmath.h').read_text(), re.M))
+    designed = {n for names in cases.GROUPS.values() for n in names}
+    if exported != designed:
+        raise RuntimeError('missing/extra function groups: ' + repr(exported ^ designed))
+    registered = set(re.findall(r'\{\s*"[a-z_]+",\s*"(\w+)",\s*T_',
+                                (ROOT / 'src2/test_dmath.c').read_text()))
+    if registered != designed:
+        raise RuntimeError('C runner groups differ: ' + repr(registered ^ designed))
+    DEST.mkdir(parents=True, exist_ok=True)
+    total = 0
+    for group, names in cases.GROUPS.items():
+        for name in names:
+            rows = getattr(cases, 'cases_' + name)()
+            if len({row.name for row in rows}) != len(rows):
+                raise RuntimeError('duplicate case name in ' + name)
+            path = DEST / (name + '.txt')
+            content = render(name, rows, path)
+            if args.check:
+                if not path.exists() or path.read_text() != content:
+                    raise RuntimeError(str(path) + ' is out of date')
+            else:
+                path.write_text(content, encoding='ascii', newline='\n')
+            total += len(rows)
+            print(group + '/' + name + ': ' + str(len(rows)) + ' cases', flush=True)
+    print(str(len(designed)) + ' functions, ' + str(total) + ' named cases')
+
+
+if __name__ == '__main__':
+    main()

+ 229 - 0
scripts/dmath/oracle.py

@@ -0,0 +1,229 @@
+"""Independent binary64 references. No host libm and no calls to dmath.
+
+Integer/Fraction arithmetic handles exact operations. Decimal handles roots,
+exponentials and logs; Machin's formula and convergent series handle angles.
+The generator requires identical rounded results at two different precisions.
+"""
+
+from decimal import Decimal as D, getcontext, ROUND_HALF_EVEN
+from fractions import Fraction
+from functools import lru_cache
+import struct
+
+SIGN = 1 << 63
+INF = 0x7FF0000000000000
+NAN = 0x7FF8000000000000
+MASK = SIGN - 1
+
+
+def bits(x):
+    return struct.unpack('>Q', struct.pack('>d', x))[0]
+
+
+def value(u):
+    return struct.unpack('>d', struct.pack('>Q', u))[0]
+
+
+def rounded(x):
+    if isinstance(x, D) and x.is_nan():
+        return NAN
+    try:
+        return bits(float(x))
+    except OverflowError:
+        return INF | (SIGN if x < 0 else 0)
+
+
+def atan_series(x):
+    term = total = x
+    square = -x * x
+    n = 1
+    while True:
+        term *= square
+        after = total + term / (2 * n + 1)
+        if after == total:
+            return total
+        total = after
+        n += 1
+
+
+@lru_cache(None)
+def pi(precision):
+    assert precision == getcontext().prec
+    return 16 * atan_series(D(1) / 5) - 4 * atan_series(D(1) / 239)
+
+
+def atan(x):
+    if x.is_zero():
+        return x
+    if x.is_signed():
+        return -atan(-x)
+    if x > 1:
+        return pi(getcontext().prec) / 2 - atan(1 / x)
+    scale = 1
+    while x > D('0.03125'):
+        x = x / (1 + (1 + x * x).sqrt())
+        scale *= 2
+    return scale * atan_series(x)
+
+
+def atan2(y, x):
+    p = pi(getcontext().prec)
+    if y.is_nan() or x.is_nan():
+        return D('NaN')
+    if y.is_zero():
+        return p.copy_sign(y) if x.is_signed() else y
+    if x.is_zero():
+        return (p / 2).copy_sign(y)
+    if y.is_infinite():
+        angle = p / 4 if x.is_infinite() else p / 2
+        if x.is_infinite() and x.is_signed():
+            angle = 3 * p / 4
+        return angle.copy_sign(y)
+    if x.is_infinite():
+        return (p if x.is_signed() else D(0)).copy_sign(y)
+    angle = atan(abs(y / x))
+    if x.is_signed():
+        angle = p - angle
+    return angle.copy_sign(y)
+
+
+def sincos(x):
+    if x.is_zero():
+        return x, D(1)
+    half_pi = pi(getcontext().prec) / 2
+    quadrant = (x / half_pi).to_integral_value(rounding=ROUND_HALF_EVEN)
+    r = x - quadrant * half_pi
+    sin_term = sine = r
+    cos_term = cosine = D(1)
+    square = -r * r
+    n = 1
+    while True:
+        sin_term = sin_term * square / ((2 * n) * (2 * n + 1))
+        cos_term = cos_term * square / ((2 * n - 1) * (2 * n))
+        s, c = sine + sin_term, cosine + cos_term
+        if s == sine and c == cosine:
+            break
+        sine, cosine = s, c
+        n += 1
+    return [(sine, cosine), (cosine, -sine), (-sine, -cosine),
+            (-cosine, sine)][int(quadrant) % 4]
+
+
+def exponential(x):
+    # These bounds are outside the finite/nonzero binary64 result range.
+    if x > 1500:
+        return D('Infinity')
+    if x < -1500:
+        return D(0)
+    return x.exp()
+
+
+def reference(name, a, b=0):
+    """Return output words (two for modf/sincos, one otherwise)."""
+    x, y = value(a), value(b)
+    ax, ay = a & MASK, b & MASK
+    nx, ny = ax > INF, ay > INF
+    if name == 'isnan':
+        return (int(nx),)
+    if name == 'isinf':
+        return (int(ax == INF),)
+    if name == 'isfinite':
+        return (int(ax < INF),)
+    if name == 'isnormal':
+        return (int(0x0010000000000000 <= ax < INF),)
+    if name == 'fabs':
+        return (ax,)
+    if name == 'copysign':
+        return (ax | (b & SIGN),)
+    if name in ('fmin', 'fmax'):
+        if nx:
+            return (NAN if ny else b,)
+        if ny:
+            return (a,)
+        if ax == 0 and ay == 0:
+            return ((a | b) if name == 'fmin' else (a & b),)
+        return (a if (x < y if name == 'fmin' else x > y) else b,)
+    if name == 'pow':
+        if y == 0 or x == 1:
+            return (bits(1.0),)
+        if nx or ny:
+            return (NAN,)
+        if ay == INF:
+            if abs(x) == 1:
+                return (bits(1.0),)
+            return (INF if (abs(x) > 1) == (y > 0) else 0,)
+        odd = y.is_integer() and abs(y) < 2**53 and int(y) % 2 != 0
+        sign = SIGN if (a & SIGN) and odd else 0
+        if ax == 0:
+            return (sign | (INF if y < 0 else 0),)
+        if ax == INF:
+            return (sign | (INF if y > 0 else 0),)
+        if x < 0 and not y.is_integer():
+            return (NAN,)
+        if y.is_integer() and abs(y) <= 4097:
+            return (rounded(Fraction(x) ** int(y)),)
+        z = exponential(D.from_float(y) * D.from_float(abs(x)).ln())
+        return (rounded(z) | sign,)
+    if nx or (name in ('atan2', 'fmod', 'log_base') and ny):
+        return (NAN, NAN) if name in ('modf', 'sincos') else (NAN,)
+    if name in ('ceil', 'floor', 'trunc', 'modf'):
+        if ax == INF or ax == 0:
+            return (a & SIGN, a) if name == 'modf' else (a,)
+        exact = Fraction(x)
+        integer = int(exact)
+        if name == 'ceil':
+            integer = -((-exact.numerator) // exact.denominator)
+        if name == 'floor':
+            integer = exact.numerator // exact.denominator
+        integral = bits(float(integer)) if integer else a & SIGN
+        if name == 'modf':
+            fraction = exact - integer
+            return (rounded(fraction) if fraction else a & SIGN, integral)
+        return (integral,)
+    if name == 'fmod':
+        if ay == 0 or ax == INF:
+            return (NAN,)
+        if ay == INF or ax == 0:
+            return (a,)
+        q = int(Fraction(x) / Fraction(y))
+        remainder = Fraction(x) - q * Fraction(y)
+        return (rounded(remainder) if remainder else a & SIGN,)
+
+    dx, dy = D.from_float(x), D.from_float(y)
+    if name == 'sqrt':
+        return (rounded(dx.sqrt()) if x >= 0 else NAN,)
+    if name == 'cbrt':
+        if ax == 0 or ax == INF:
+            return (a,)
+        return (rounded(exponential(abs(dx).ln() / 3)) | (a & SIGN),)
+    if name in ('exp', 'exp2', 'exp10'):
+        # Resolve exact halfway/subnormal cases using rationals, rather than
+        # allowing the last Decimal rounding error to decide a binary64 tie.
+        if name == 'exp2' and ax < INF and x.is_integer() and abs(x) <= 1100:
+            return (rounded(Fraction(2) ** int(x)),)
+        if name == 'exp10' and ax < INF and x.is_integer() and abs(x) <= 500:
+            return (rounded(Fraction(10) ** int(x)),)
+        factor = {'exp': D(1), 'exp2': D(2).ln(), 'exp10': D(10).ln()}[name]
+        return (rounded(exponential(dx * factor)),)
+    if name in ('log', 'log2', 'log10', 'log_base'):
+        logarithm = dx.ln()
+        divisor = {'log': D(1), 'log2': D(2).ln(), 'log10': D(10).ln()}
+        denominator = dy.ln() if name == 'log_base' else divisor[name]
+        return (rounded(logarithm / denominator),)
+    if name in ('sin', 'cos', 'tan', 'sincos'):
+        if ax == INF:
+            return (NAN, NAN) if name == 'sincos' else (NAN,)
+        s, c = sincos(dx)
+        if name == 'sincos':
+            return rounded(s), rounded(c)
+        return (rounded({'sin': s, 'cos': c, 'tan': s / c}[name]),)
+    if name == 'atan':
+        return (rounded(atan(dx)),)
+    if name == 'atan2':
+        return (rounded(atan2(dx, dy)),)  # arguments are (y, x)
+    if name in ('asin', 'acos'):
+        if abs(dx) > 1:
+            return (NAN,)
+        root = (1 - dx * dx).sqrt()
+        return (rounded(atan2(dx, root) if name == 'asin' else atan2(root, dx)),)
+    raise ValueError(name)

+ 5 - 17
src/bindings/py_number.c

@@ -104,35 +104,23 @@ static bool number__pow__(int argc, py_Ref argv) {
                 py_newfloat(py_retval(), dmath_pow(lhs, rhs));
                 py_newfloat(py_retval(), dmath_pow(lhs, rhs));
             }
             }
         } else {
         } else {
-            // Fixed-width integer powers must not invoke signed-overflow UB.
-            // Keep the exact integer result when representable, including INT64_MIN.
-            bool negative = lhs < 0 && (rhs & 1);
-            uint64_t limit = negative ? UINT64_C(0x8000000000000000) : INT64_MAX;
-            uint64_t base = lhs < 0 ? 0 - (uint64_t)lhs : (uint64_t)lhs;
+            // Preserve 64-bit wraparound using defined unsigned arithmetic.
+            uint64_t base = (uint64_t)lhs;
             uint64_t ret = 1;
             uint64_t ret = 1;
             while(true) {
             while(true) {
-                if(rhs & 1) {
-                    if(base && ret > limit / base) return OverflowError("integer power overflow");
-                    ret *= base;
-                }
+                if(rhs & 1) ret *= base;
                 rhs >>= 1;
                 rhs >>= 1;
                 if(!rhs) break;
                 if(!rhs) break;
-                if(base && base > limit / base) return OverflowError("integer power overflow");
                 base *= base;
                 base *= base;
             }
             }
-            py_i64 result = negative && ret ? -(py_i64)(ret - 1) - 1 : (py_i64)ret;
+            py_i64 result = ret <= INT64_MAX ? (py_i64)ret : -1 - (py_i64)(UINT64_MAX - ret);
             py_newint(py_retval(), result);
             py_newint(py_retval(), result);
         }
         }
     } else {
     } else {
         py_f64 lhs, rhs;
         py_f64 lhs, rhs;
         if(!py_castfloat(&argv[0], &lhs)) return false;
         if(!py_castfloat(&argv[0], &lhs)) return false;
         if(try_castfloat(&argv[1], &rhs)) {
         if(try_castfloat(&argv[1], &rhs)) {
-            if(lhs == 0 && rhs < 0 && dmath_isfinite(rhs))
-                return ZeroDivisionError("0.0 cannot be raised to a negative power");
-            double result = dmath_pow(lhs, rhs);
-            if(dmath_isinf(result) && dmath_isfinite(lhs) && dmath_isfinite(rhs))
-                return OverflowError("numerical result out of range");
-            py_newfloat(py_retval(), result);
+            py_newfloat(py_retval(), dmath_pow(lhs, rhs));
         } else {
         } else {
             py_newnotimplemented(py_retval());
             py_newnotimplemented(py_retval());
         }
         }

+ 13 - 455
src/common/dmath.c

@@ -1,6 +1,5 @@
 #include "pocketpy/common/dmath.h"
 #include "pocketpy/common/dmath.h"
 #include "pocketpy/common/algorithm.h"
 #include "pocketpy/common/algorithm.h"
-#include "pocketpy/common/_log_spline_tbl.h"
 #include <stdint.h>
 #include <stdint.h>
 
 
 // hardware sqrt, see `dmath_sqrt`
 // hardware sqrt, see `dmath_sqrt`
@@ -15,165 +14,22 @@ union Float64Bits {
     uint64_t i;
     uint64_t i;
 };
 };
 
 
-/* IEEE 754 double precision floating point data manipulation */
-typedef union 
-{
-    double   f;
-    uint64_t u;
-    struct {int32_t  i0,i1;} s;
-}  udi_t;
-
-// https://github.com/akohlmey/fastermath/blob/master/src/exp.c#L63
-double dmath_exp2(double x) {
-    if (x > 1000) return DMATH_INFINITY;
-    if (x < -1000) return 0;
-	if (dmath_isnan(x)) return DMATH_NAN;
-    
-    const int FM_DOUBLE_BIAS = 1023;
-
-    static const double fm_exp2_q[] = {
-    /*  1.00000000000000000000e0, */
-        2.33184211722314911771e2,
-        4.36821166879210612817e3
-    };
-    static const double fm_exp2_p[] = {
-        2.30933477057345225087e-2,
-        2.02020656693165307700e1,
-        1.51390680115615096133e3
-    };
-
-    double   ipart, fpart, px, qx;
-    udi_t    epart;
-
-    ipart = dmath_floor(x+0.5);
-    fpart = x - ipart;
-
-    // FM_DOUBLE_INIT_EXP(epart,ipart);
-    epart.s.i0 = 0;
-    epart.s.i1 = (((int) ipart) + FM_DOUBLE_BIAS) << 20;
-
-    x = fpart*fpart;
-
-    px =        fm_exp2_p[0];
-    px = px*x + fm_exp2_p[1];
-    qx =    x + fm_exp2_q[0];
-    px = px*x + fm_exp2_p[2];
-    qx = qx*x + fm_exp2_q[1];
-
-    px = px * fpart;
-
-    x = 1.0 + 2.0*(px/(qx-px));
-    return epart.f*x;
-}
-
-double dmath_log2(double x) {
-	if(x < 0) return DMATH_NAN;
-	if(x == 0) return -DMATH_INFINITY;
-	if(x == DMATH_INFINITY) return DMATH_INFINITY;
-	if(dmath_isnan(x)) return DMATH_NAN;
-
-    const double fm_log_dinv =  4.09600000000000000000e+03;
-    const double fm_log_dsq6 =  9.93410746256510361521e-09;
-
-    const int FM_DOUBLE_BIAS = 1023;
-    const int FM_DOUBLE_EMASK = 2146435072;
-    const int FM_DOUBLE_MBITS = 20;
-    const int FM_DOUBLE_MMASK = 1048575;
-    const int FM_DOUBLE_EZERO = 1072693248;
-
-    const int FM_SPLINE_SHIFT = 8;
-
-    udi_t val;
-    double a,b,y;
-    int32_t hx, ipart;
-
-    val.f = x;
-    hx = val.s.i1;
-    
-    /* extract exponent and subtract bias */
-    ipart = (((hx & FM_DOUBLE_EMASK) >> FM_DOUBLE_MBITS) - FM_DOUBLE_BIAS);
-
-    /* mask out exponent to get the prefactor to 2**ipart */
-    hx &= FM_DOUBLE_MMASK;
-    val.s.i1 = hx | FM_DOUBLE_EZERO;
-    x = val.f;
-
-    /* table index */
-    hx >>= FM_SPLINE_SHIFT;
-
-    /* compute x value matching table index */
-    val.s.i0 = 0;
-    val.s.i1 = FM_DOUBLE_EZERO | (hx << FM_SPLINE_SHIFT);
-    b = (x - val.f) * fm_log_dinv;
-    a = 1.0 - b;
-
-    /* evaluate spline */
-    y = a * fm_log_q1[hx] + b * fm_log_q1[hx+1];
-    a = (a*a*a-a) * fm_log_q2[hx];
-    b = (b*b*b-b) * fm_log_q2[hx+1];
-    y += (a + b) * fm_log_dsq6;
-
-    return ((double) ipart) + (y * DMATH_LOG2_E);
-}
-
-double dmath_exp(double x) {
-    return dmath_exp2(x * DMATH_LOG2_E); // log2(e)
-}
-
-double dmath_exp10(double x) {
-    return dmath_exp2(x * 3.321928094887362); // log2(10)
-}
-
-double dmath_log(double x) {
-    return dmath_log2(x) / DMATH_LOG2_E; // log2(e)
-}
-
-double dmath_log10(double x) {
-    return dmath_log2(x) / 3.321928094887362; // log2(10)
-}
-
-double dmath_pow(double base, double exp) {
-    int64_t exp_int = (int64_t)exp;
-    if(exp_int == exp) {
-        if(exp_int == 0) return 1;
-        if(exp_int < 0) {
-			if(base == 0) return DMATH_NAN;
-            base = 1 / base;
-            exp_int = -exp_int;
-        }
-        double res = 1;
-        while(exp_int > 0) {
-            if(exp_int & 1) res *= base;
-            base *= base;
-            exp_int >>= 1;
-        }
-        return res;
-    }
-    if (base > 0) {
-		if(base == 1.0) return 1.0;
-        return dmath_exp(exp * dmath_log(base));
-    }
-    if (base == 0) {
-        if (exp > 0) return 0;
-        if (exp == 0) return 1;
-    }
-    return DMATH_NAN;
-}
-
 // IEEE 754 requires sqrt to be correctly rounded, so the hardware instruction
 // IEEE 754 requires sqrt to be correctly rounded, so the hardware instruction
 // returns the same bits on every platform (and matches CPython).
 // returns the same bits on every platform (and matches CPython).
 // libm is never used: every hardware branch below is guaranteed to emit the instruction,
 // libm is never used: every hardware branch below is guaranteed to emit the instruction,
 // and other targets use a software sqrt which is also correctly rounded (same bits, but slow).
 // and other targets use a software sqrt which is also correctly rounded (same bits, but slow).
 double dmath_sqrt(double x) {
 double dmath_sqrt(double x) {
     if(x < 0) return DMATH_NAN;
     if(x < 0) return DMATH_NAN;
-#if defined(__SSE2__) || defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2)
+// PK_DMATH_SOFT_SQRT exercises the fallback on hardware-sqrt hosts in tests.
+#if !defined(PK_DMATH_SOFT_SQRT) && \
+    (defined(__SSE2__) || defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2))
     // x86 with sse2: sqrtsd
     // x86 with sse2: sqrtsd
     __m128d v = _mm_set_sd(x);
     __m128d v = _mm_set_sd(x);
     return _mm_cvtsd_f64(_mm_sqrt_sd(v, v));
     return _mm_cvtsd_f64(_mm_sqrt_sd(v, v));
-#elif defined(__aarch64__) || defined(_M_ARM64)
+#elif !defined(PK_DMATH_SOFT_SQRT) && (defined(__aarch64__) || defined(_M_ARM64))
     // aarch64: fsqrt
     // aarch64: fsqrt
     return vget_lane_f64(vsqrt_f64(vdup_n_f64(x)), 0);
     return vget_lane_f64(vsqrt_f64(vdup_n_f64(x)), 0);
-#elif defined(__arm__) && defined(__ARM_FP) && (__ARM_FP & 8)
+#elif !defined(PK_DMATH_SOFT_SQRT) && defined(__arm__) && defined(__ARM_FP) && (__ARM_FP & 8)
     // arm32 with a double precision vfp: vsqrt
     // arm32 with a double precision vfp: vsqrt
     // (`__builtin_sqrt` is not used because it may call libm to set errno)
     // (`__builtin_sqrt` is not used because it may call libm to set errno)
     register double d0 __asm__("d0") = x;
     register double d0 __asm__("d0") = x;
@@ -218,290 +74,7 @@ double dmath_sqrt(double x) {
 #endif
 #endif
 }
 }
 
 
-// https://github.com/kraj/musl/blob/kraj/master/src/math/sincos.c
-static double __sin(double x, double y, int iy)
-{
-static const double
-S1  = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */
-S2  =  8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */
-S3  = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */
-S4  =  2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */
-S5  = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */
-S6  =  1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */
-
-	double z,r,v,w;
-
-	z = x*x;
-	w = z*z;
-	r = S2 + z*(S3 + z*S4) + z*w*(S5 + z*S6);
-	v = z*x;
-	if (iy == 0)
-		return x + v*(S1 + z*r);
-	else
-		return x - ((z*(0.5*y - v*r) - y) - v*S1);
-}
-
-static double __cos(double x, double y)
-{
-static const double
-C1  =  4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */
-C2  = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */
-C3  =  2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */
-C4  = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */
-C5  =  2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */
-C6  = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */
-
-	double hz,z,r,w;
-
-	z  = x*x;
-	w  = z*z;
-	r  = z*(C1+z*(C2+z*C3)) + w*w*(C4+z*(C5+z*C6));
-	hz = 0.5*z;
-	w  = 1.0-hz;
-	return w + (((1.0-w)-hz) + (z*r-x*y));
-}
-
-int __rem_pio2(double x, double *y)
-{
-static const double
-toint   = 1.5/2.22044604925031308085e-16,
-pio4    = 0x1.921fb54442d18p-1,
-invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
-pio2_1  = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */
-pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */
-pio2_2  = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */
-pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */
-pio2_3  = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */
-pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
-
-	union Float64Bits u = { .f = x };
-	double z,w,t,r,fn;
-	double tx[3],ty[2];
-	uint32_t ix;
-	int sign, n, ex, ey, i;
-
-	sign = u.i>>63;
-	ix = u.i>>32 & 0x7fffffff;
-	if (ix <= 0x400f6a7a) {  /* |x| ~<= 5pi/4 */
-		if ((ix & 0xfffff) == 0x921fb)  /* |x| ~= pi/2 or 2pi/2 */
-			goto medium;  /* cancellation -- use medium case */
-		if (ix <= 0x4002d97c) {  /* |x| ~<= 3pi/4 */
-			if (!sign) {
-				z = x - pio2_1;  /* one round good to 85 bits */
-				y[0] = z - pio2_1t;
-				y[1] = (z-y[0]) - pio2_1t;
-				return 1;
-			} else {
-				z = x + pio2_1;
-				y[0] = z + pio2_1t;
-				y[1] = (z-y[0]) + pio2_1t;
-				return -1;
-			}
-		} else {
-			if (!sign) {
-				z = x - 2*pio2_1;
-				y[0] = z - 2*pio2_1t;
-				y[1] = (z-y[0]) - 2*pio2_1t;
-				return 2;
-			} else {
-				z = x + 2*pio2_1;
-				y[0] = z + 2*pio2_1t;
-				y[1] = (z-y[0]) + 2*pio2_1t;
-				return -2;
-			}
-		}
-	}
-	if (ix <= 0x401c463b) {  /* |x| ~<= 9pi/4 */
-		if (ix <= 0x4015fdbc) {  /* |x| ~<= 7pi/4 */
-			if (ix == 0x4012d97c)  /* |x| ~= 3pi/2 */
-				goto medium;
-			if (!sign) {
-				z = x - 3*pio2_1;
-				y[0] = z - 3*pio2_1t;
-				y[1] = (z-y[0]) - 3*pio2_1t;
-				return 3;
-			} else {
-				z = x + 3*pio2_1;
-				y[0] = z + 3*pio2_1t;
-				y[1] = (z-y[0]) + 3*pio2_1t;
-				return -3;
-			}
-		} else {
-			if (ix == 0x401921fb)  /* |x| ~= 4pi/2 */
-				goto medium;
-			if (!sign) {
-				z = x - 4*pio2_1;
-				y[0] = z - 4*pio2_1t;
-				y[1] = (z-y[0]) - 4*pio2_1t;
-				return 4;
-			} else {
-				z = x + 4*pio2_1;
-				y[0] = z + 4*pio2_1t;
-				y[1] = (z-y[0]) + 4*pio2_1t;
-				return -4;
-			}
-		}
-	}
-	if (ix < 0x413921fb) {  /* |x| ~< 2^20*(pi/2), medium size */
-medium:
-		/* rint(x/(pi/2)) */
-		fn = (double)x*invpio2 + toint - toint;
-		n = (int32_t)fn;
-		r = x - fn*pio2_1;
-		w = fn*pio2_1t;  /* 1st round, good to 85 bits */
-		/* Matters with directed rounding. */
-		if ((r - w < -pio4)) {
-			n--;
-			fn--;
-			r = x - fn*pio2_1;
-			w = fn*pio2_1t;
-		} else if ((r - w > pio4)) {
-			n++;
-			fn++;
-			r = x - fn*pio2_1;
-			w = fn*pio2_1t;
-		}
-		y[0] = r - w;
-		u.f = y[0];
-		ey = u.i>>52 & 0x7ff;
-		ex = ix>>20;
-		if (ex - ey > 16) { /* 2nd round, good to 118 bits */
-			t = r;
-			w = fn*pio2_2;
-			r = t - w;
-			w = fn*pio2_2t - ((t-r)-w);
-			y[0] = r - w;
-			u.f = y[0];
-			ey = u.i>>52 & 0x7ff;
-			if (ex - ey > 49) {  /* 3rd round, good to 151 bits, covers all cases */
-				t = r;
-				w = fn*pio2_3;
-				r = t - w;
-				w = fn*pio2_3t - ((t-r)-w);
-				y[0] = r - w;
-			}
-		}
-		y[1] = (r - y[0]) - w;
-		return n;
-	}
-
-    (void)tx;
-    (void)ty;
-    (void)i;
-    return 0;
-#if 0
-	/*
-	 * all other (large) arguments
-	 */
-	if (ix >= 0x7ff00000) {  /* x is inf or NaN */
-		y[0] = y[1] = x - x;
-		return 0;
-	}
-	/* set z = scalbn(|x|,-ilogb(x)+23) */
-	u.f = x;
-	u.i &= (uint64_t)-1>>12;
-	u.i |= (uint64_t)(0x3ff + 23)<<52;
-	z = u.f;
-	for (i=0; i < 2; i++) {
-		tx[i] = (double)(int32_t)z;
-		z     = (z-tx[i])*0x1p24;
-	}
-	tx[i] = z;
-	/* skip zero terms, first term is non-zero */
-	while (tx[i] == 0.0)
-		i--;
-	n = __rem_pio2_large(tx,ty,(int)(ix>>20)-(0x3ff+23),i+1,1);
-	if (sign) {
-		y[0] = -ty[0];
-		y[1] = -ty[1];
-		return -n;
-	}
-	y[0] = ty[0];
-	y[1] = ty[1];
-	return n;
-#endif
-}
-
-void dmath_sincos(double x, double *sin, double *cos) {
-	double y[2], s, c;
-	uint32_t ix;
-	unsigned n;
-
-	//GET_HIGH_WORD(ix, x);
-    union Float64Bits u = { .f = x };
-    ix = (uint32_t)(u.i >> 32);
-
-	ix &= 0x7fffffff;
-
-	/* |x| ~< pi/4 */
-	if (ix <= 0x3fe921fb) {
-		/* if |x| < 2**-27 * sqrt(2) */
-		if (ix < 0x3e46a09e) {
-			/* raise inexact if x!=0 and underflow if subnormal */
-
-			// FORCE_EVAL(ix < 0x00100000 ? x/0x1p120f : x+0x1p120f);
-            volatile double y_force_eval;
-            y_force_eval = ix < 0x00100000 ? x/0x1p120f : x+0x1p120f;
-            (void)y_force_eval;
-
-			*sin = x;
-			*cos = 1.0;
-			return;
-		}
-		*sin = __sin(x, 0.0, 0);
-		*cos = __cos(x, 0.0);
-		return;
-	}
-
-	/* sincos(Inf or NaN) is NaN */
-	if (ix >= 0x7ff00000) {
-		*sin = *cos = x - x;
-		return;
-	}
-
-	/* argument reduction needed */
-	n = __rem_pio2(x, y);
-	s = __sin(y[0], y[1], 1);
-	c = __cos(y[0], y[1]);
-	switch (n&3) {
-	case 0:
-		*sin = s;
-		*cos = c;
-		break;
-	case 1:
-		*sin = c;
-		*cos = -s;
-		break;
-	case 2:
-		*sin = -s;
-		*cos = -c;
-		break;
-	case 3:
-	default:
-		*sin = -c;
-		*cos = s;
-		break;
-	}
-}
-
-double dmath_sin(double x) {
-    double s, c;
-    dmath_sincos(x, &s, &c);
-    return s;
-}
-
-double dmath_cos(double x) {
-    double s, c;
-    dmath_sincos(x, &s, &c);
-    return c;
-}
-
-double dmath_tan(double x) {
-    double s, c;
-    dmath_sincos(x, &s, &c);
-    return s / c;
-}
-
+// sin/cos/tan/sincos live in dmath_openlibm.c.
 // dmath_asin / dmath_acos / dmath_atan / dmath_atan2 live in dmath_zig.c
 // dmath_asin / dmath_acos / dmath_atan / dmath_atan2 live in dmath_zig.c
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -529,7 +102,6 @@ int dmath_isfinite(double x) {
 // https://github.com/kraj/musl/blob/kraj/master/src/math/fmod.c
 // https://github.com/kraj/musl/blob/kraj/master/src/math/fmod.c
 double dmath_fmod(double x, double y) {
 double dmath_fmod(double x, double y) {
 	if(y == 0) return DMATH_NAN;
 	if(y == 0) return DMATH_NAN;
-	
 	union Float64Bits ux = { .f = x }, uy = { .f = y };
 	union Float64Bits ux = { .f = x }, uy = { .f = y };
 	int ex = ux.i>>52 & 0x7ff;
 	int ex = ux.i>>52 & 0x7ff;
 	int ey = uy.i>>52 & 0x7ff;
 	int ey = uy.i>>52 & 0x7ff;
@@ -609,27 +181,7 @@ double dmath_fabs(double x) {
 	return u.f;
 	return u.f;
 }
 }
 
 
-double dmath_ceil(double x) {
-	if(!dmath_isfinite(x)) return x;
-    int64_t int_part = (int64_t)x;
-    if (x > 0 && x != (double)int_part) {
-        return (double)(int_part + 1);
-    }
-    return (double)int_part;
-}
-
-double dmath_floor(double x) {
-	if(!dmath_isfinite(x)) return x;
-    int64_t int_part = (int64_t)x;
-    if (x < 0 && x != (double)int_part) {
-        return (double)(int_part - 1);
-    }
-    return (double)int_part;
-}
-
-double dmath_trunc(double x) {
-    return (double)((int64_t)x);
-}
+// ceil/floor/trunc live in dmath_openlibm.c.
 
 
 // https://github.com/kraj/musl/blob/kraj/master/src/math/modf.c
 // https://github.com/kraj/musl/blob/kraj/master/src/math/modf.c
 double dmath_modf(double x, double* iptr) {
 double dmath_modf(double x, double* iptr) {
@@ -665,9 +217,15 @@ double dmath_modf(double x, double* iptr) {
 }
 }
 
 
 double dmath_fmin(double x, double y) {
 double dmath_fmin(double x, double y) {
+    if(dmath_isnan(x)) return y;
+    if(dmath_isnan(y)) return x;
+    if(x == y) return (pk_dmath_bits(x) >> 63) ? x : y;
     return (x < y) ? x : y;
     return (x < y) ? x : y;
 }
 }
 
 
 double dmath_fmax(double x, double y) {
 double dmath_fmax(double x, double y) {
+    if(dmath_isnan(x)) return y;
+    if(dmath_isnan(y)) return x;
+    if(x == y) return (pk_dmath_bits(x) >> 63) ? y : x;
     return (x > y) ? x : y;
     return (x > y) ? x : y;
 }
 }

+ 2319 - 0
src/common/dmath_openlibm.c

@@ -0,0 +1,2319 @@
+/*
+ * pocketpy's fixed binary64 mathematical kernels.
+ * Derived from OpenLibm v0.8.8, commit
+ * 5fe399749f9276eaa0b8403e507470da05cbbb3f.
+ * See 3rd/openlibm/README.md for provenance and the numerical contract.
+ * Original notices are retained beside each kernel below.
+ *
+ * Local changes: private names, function-local constants, endian-independent
+ * word access, defined integer arithmetic, and canonical NaNs.
+ * The approximation coefficients and floating-point evaluation order are fixed.
+ */
+#include "pocketpy/common/dmath.h"
+#include <float.h>
+#include <stdint.h>
+#include <string.h>
+
+// Floating-point options are supplied by the build configuration.
+
+static uint64_t dmath_ol_bits(double x) {
+    uint64_t bits;
+    memcpy(&bits, &x, sizeof(bits));
+    return bits;
+}
+
+static double dmath_ol_from_bits(uint64_t bits) {
+    double x;
+    memcpy(&x, &bits, sizeof(x));
+    return x;
+}
+
+/* Avoid implementation-defined unsigned-to-signed conversions of bit words. */
+static int32_t dmath_ol_i32(uint32_t word) {
+    return word <= INT32_MAX ? (int32_t)word : (int32_t)((int64_t)word - 0x100000000LL);
+}
+
+static double dmath_ol_result(double x) {
+    uint64_t magnitude = dmath_ol_bits(x) & UINT64_C(0x7fffffffffffffff);
+    return magnitude > UINT64_C(0x7ff0000000000000)
+               ? dmath_ol_from_bits(UINT64_C(0x7ff8000000000000))
+               : x;
+}
+
+#define DMATH_OL_GET_HIGH_WORD(hi, x) ((hi) = dmath_ol_i32((uint32_t)(dmath_ol_bits(x) >> 32)))
+#define DMATH_OL_GET_LOW_WORD(lo, x) ((lo) = dmath_ol_i32((uint32_t)dmath_ol_bits(x)))
+#define DMATH_OL_EXTRACT_WORDS(hi, lo, x)                                                          \
+    do {                                                                                           \
+        uint64_t dmath_ol_words = dmath_ol_bits(x);                                                \
+        (hi) = dmath_ol_i32((uint32_t)(dmath_ol_words >> 32));                                     \
+        (lo) = dmath_ol_i32((uint32_t)dmath_ol_words);                                             \
+    } while(0)
+#define DMATH_OL_INSERT_WORDS(x, hi, lo)                                                           \
+    ((x) = dmath_ol_from_bits(((uint64_t)(uint32_t)(hi) << 32) | (uint32_t)(lo)))
+#define DMATH_OL_SET_HIGH_WORD(x, hi)                                                              \
+    ((x) = dmath_ol_from_bits((dmath_ol_bits(x) & UINT64_C(0xffffffff)) |                          \
+                              ((uint64_t)(uint32_t)(hi) << 32)))
+#define DMATH_OL_SET_LOW_WORD(x, lo)                                                               \
+    ((x) = dmath_ol_from_bits((dmath_ol_bits(x) & UINT64_C(0xffffffff00000000)) | (uint32_t)(lo)))
+#define DMATH_OL_STRICT_ASSIGN(type, dst, value) ((dst) = (value))
+
+// OpenLibm src/k_log.h
+/* @(#)e_log.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * dmath_ol_log1p_kernel(f):
+ * Return log(1+f) - f for 1+f in ~[dmath_sqrt(2)/2, dmath_sqrt(2)].
+ *
+ * The following describes the overall strategy for computing
+ * logarithms in base e.  The argument reduction and adding the final
+ * term of the polynomial are done by the caller for increased accuracy
+ * when different bases are used.
+ *
+ * Method :
+ *   1. Argument Reduction: find k and f such that
+ *			x = 2^k * (1+f),
+ *	   where  dmath_sqrt(2)/2 < 1+f < dmath_sqrt(2) .
+ *
+ *   2. Approximation of log(1+f).
+ *	Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
+ *		 = 2s + 2/3 s**3 + 2/5 s**5 + .....,
+ *	     	 = 2s + s*R
+ *      We use a special Reme algorithm on [0,0.1716] to generate
+ * 	a polynomial of degree 14 to approximate R The maximum error
+ *	of this polynomial approximation is bounded by 2**-58.45. In
+ *	other words,
+ *		        2      4      6      8      10      12      14
+ *	    R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s  +Lg6*s  +Lg7*s
+ *  	(the values of Lg1 to Lg7 are listed in the program)
+ *	and
+ *	    |      2          14          |     -58.45
+ *	    | Lg1*s +...+Lg7*s    -  R(z) | <= 2
+ *	    |                             |
+ *	Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
+ *	In order to guarantee error in log below 1ulp, we compute log
+ *	by
+ *		log(1+f) = f - s*(f - R)	(if f is not too large)
+ *		log(1+f) = f - (hfsq - s*(hfsq+R)).	(better accuracy)
+ *
+ *	3. Finally,  log(x) = k*ln2 + log(1+f).
+ *			    = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
+ *	   Here ln2 is split into two floating point number:
+ *			ln2_hi + ln2_lo,
+ *	   where n*ln2_hi is always exact for |n| < 2000.
+ *
+ * Special cases:
+ *	log(x) is NaN with signal if x < 0 (including -INF) ;
+ *	log(+INF) is +INF; log(0) is -INF with signal;
+ *	log(NaN) is that NaN with no signal.
+ *
+ * Accuracy:
+ *	according to an error analysis, the error is always less than
+ *	1 ulp (unit in the last place).
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+static inline double dmath_ol_log1p_kernel(double f) {
+    static const double Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */
+        Lg2 = 3.999999999940941908e-01,                 /* 3FD99999 9997FA04 */
+        Lg3 = 2.857142874366239149e-01,                 /* 3FD24924 94229359 */
+        Lg4 = 2.222219843214978396e-01,                 /* 3FCC71C5 1D8E78AF */
+        Lg5 = 1.818357216161805012e-01,                 /* 3FC74664 96CB03DE */
+        Lg6 = 1.531383769920937332e-01,                 /* 3FC39A09 D078C69F */
+        Lg7 = 1.479819860511658591e-01;                 /* 3FC2F112 DF3E5244 */
+
+    /*
+     * We always inline dmath_ol_log1p_kernel(), since doing so produces a
+     * substantial performance improvement (~40% on amd64).
+     */
+
+    double hfsq, s, z, R, w, t1, t2;
+
+    s = f / (2.0 + f);
+    z = s * s;
+    w = z * z;
+    t1 = w * (Lg2 + w * (Lg4 + w * Lg6));
+    t2 = z * (Lg1 + w * (Lg3 + w * (Lg5 + w * Lg7)));
+    R = t2 + t1;
+    hfsq = 0.5 * f * f;
+    return s * (hfsq + R);
+}
+
+// OpenLibm src/s_scalbn.c
+/* @(#)s_scalbn.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * dmath_ol_scalbn (double x, int n)
+ * dmath_ol_scalbn(x,n) returns x* 2**n  computed by  exponent
+ * manipulation rather than by actually performing an
+ * exponentiation or a multiplication.
+ */
+
+static double dmath_ol_scalbn(double x, int n) {
+    static const double two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
+        twom54 = 5.55111512312578270212e-17,                /* 0x3C900000, 0x00000000 */
+        huge = 1.0e+300, tiny = 1.0e-300;
+
+    int32_t k, hx, lx;
+    DMATH_OL_EXTRACT_WORDS(hx, lx, x);
+    k = (hx & 0x7ff00000) >> 20;                    /* extract exponent */
+    if(k == 0) {                                    /* 0 or subnormal x */
+        if((lx | (hx & 0x7fffffff)) == 0) return x; /* +-0 */
+        x *= two54;
+        DMATH_OL_GET_HIGH_WORD(hx, x);
+        k = ((hx & 0x7ff00000) >> 20) - 54;
+        if(n < -50000) return tiny * x; /*underflow*/
+    }
+    if(k == 0x7ff) return x + x; /* NaN or Inf */
+    /* Bound n before adding it: the upstream overflow check was too late. */
+    if(n > 50000) return huge * dmath_copysign(huge, x);
+    if(n < -50000) return tiny * dmath_copysign(tiny, x);
+    k = k + n;
+    if(k > 0x7fe) return huge * dmath_copysign(huge, x); /* overflow  */
+    if(k > 0)                                            /* normal result */
+    {
+        DMATH_OL_SET_HIGH_WORD(x, (hx & 0x800fffff) | (k << 20));
+        return x;
+    }
+    if(k <= -54) {
+        if(n > 50000)                              /* in case integer overflow in n+k */
+            return huge * dmath_copysign(huge, x); /*overflow*/
+        else
+            return tiny * dmath_copysign(tiny, x); /*underflow*/
+    }
+    k += 54; /* subnormal result */
+    DMATH_OL_SET_HIGH_WORD(x, (hx & 0x800fffff) | (k << 20));
+    return x * twom54;
+}
+
+// OpenLibm src/e_exp.c
+/* @(#)e_exp.c 1.6 04/04/22 */
+/*
+ * ====================================================
+ * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* dmath_ol_exp(x)
+ * Returns the exponential of x.
+ *
+ * Method
+ *   1. Argument reduction:
+ *      Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658.
+ *	Given x, find r and integer k such that
+ *
+ *               x = k*ln2 + r,  |r| <= 0.5*ln2.
+ *
+ *      Here r will be represented as r = hi-lo for better
+ *	accuracy.
+ *
+ *   2. Approximation of exp(r) by a special rational function on
+ *	the interval [0,0.34658]:
+ *	Write
+ *	    R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ...
+ *      We use a special Remes algorithm on [0,0.34658] to generate
+ * 	a polynomial of degree 5 to approximate R. The maximum error
+ *	of this polynomial approximation is bounded by 2**-59. In
+ *	other words,
+ *	    R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5
+ *  	(where z=r*r, and the values of P1 to P5 are listed below)
+ *	and
+ *	    |                  5          |     -59
+ *	    | 2.0+P1*z+...+P5*z   -  R(z) | <= 2
+ *	    |                             |
+ *	The computation of exp(r) thus becomes
+ *                             2*r
+ *		exp(r) = 1 + -------
+ *		              R - r
+ *                                 r*R1(r)
+ *		       = 1 + r + ----------- (for better accuracy)
+ *		                  2 - R1(r)
+ *	where
+ *			         2       4             10
+ *		R1(r) = r - (P1*r  + P2*r  + ... + P5*r   ).
+ *
+ *   3. Scale back to obtain exp(x):
+ *	From step 1, we have
+ *	   exp(x) = 2^k * exp(r)
+ *
+ * Special cases:
+ *	exp(INF) is INF, exp(NaN) is NaN;
+ *	exp(-INF) is 0, and
+ *	for finite argument, only exp(0)=1 is exact.
+ *
+ * Accuracy:
+ *	according to an error analysis, the error is always less than
+ *	1 ulp (unit in the last place).
+ *
+ * Misc. info.
+ *	For IEEE double
+ *	    if x >  7.09782712893383973096e+02 then exp(x) overflow
+ *	    if x < -7.45133219101941108420e+02 then exp(x) underflow
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+static double dmath_ol_exp(double x) /* default IEEE double exp */
+{
+    static const double one = 1.0,
+                        halF[2] =
+                            {
+                                0.5,
+                                -0.5,
+                            },
+                        huge = 1.0e+300,
+                        o_threshold = 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */
+        u_threshold = -7.45133219101941108420e+02,                /* 0xc0874910, 0xD52D3051 */
+        ln2HI[2] =
+            {
+                6.93147180369123816490e-01, /* 0x3fe62e42, 0xfee00000 */
+                -6.93147180369123816490e-01,
+            }, /* 0xbfe62e42, 0xfee00000 */
+        ln2LO[2] =
+            {
+                1.90821492927058770002e-10, /* 0x3dea39ef, 0x35793c76 */
+                -1.90821492927058770002e-10,
+            },                               /* 0xbdea39ef, 0x35793c76 */
+        invln2 = 1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */
+        P1 = 1.66666666666666019037e-01,     /* 0x3FC55555, 0x5555553E */
+        P2 = -2.77777777770155933842e-03,    /* 0xBF66C16C, 0x16BEBD93 */
+        P3 = 6.61375632143793436117e-05,     /* 0x3F11566A, 0xAF25DE2C */
+        P4 = -1.65339022054652515390e-06,    /* 0xBEBBBD41, 0xC5D26BF1 */
+        P5 = 4.13813679705723846039e-08;     /* 0x3E663769, 0x72BEA4D0 */
+
+    static volatile double twom1000 = 9.33263618503218878990e-302; /* 2**-1000=0x01700000,0*/
+
+    double y, hi = 0.0, lo = 0.0, c, t, twopk;
+    int32_t k = 0, xsb;
+    uint32_t hx;
+
+    DMATH_OL_GET_HIGH_WORD(hx, x);
+    xsb = (hx >> 31) & 1; /* sign bit of x */
+    hx &= 0x7fffffff;     /* high word of |x| */
+
+    /* filter out non-finite argument */
+    if(hx >= 0x40862E42) { /* if |x|>=709.78... */
+        if(hx >= 0x7ff00000) {
+            uint32_t lx;
+            DMATH_OL_GET_LOW_WORD(lx, x);
+            if(((hx & 0xfffff) | lx) != 0)
+                return x + x; /* NaN */
+            else
+                return (xsb == 0) ? x : 0.0; /* exp(+-inf)={inf,0} */
+        }
+        if(x > o_threshold) return huge * huge;         /* overflow */
+        if(x < u_threshold) return twom1000 * twom1000; /* underflow */
+    }
+
+    /* this implementation gives 2.7182818284590455 for exp(1.0),
+       which is well within the allowable error. however,
+       2.718281828459045 is closer to the true value so we prefer that
+       answer, given that 1.0 is such an important argument value. */
+    if(x == 1.0) return 2.718281828459045235360;
+
+    /* argument reduction */
+    if(hx > 0x3fd62e42) {     /* if  |x| > 0.5 ln2 */
+        if(hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */
+            hi = x - ln2HI[xsb];
+            lo = ln2LO[xsb];
+            k = 1 - xsb - xsb;
+        } else {
+            k = (int)(invln2 * x + halF[xsb]);
+            t = k;
+            hi = x - t * ln2HI[0]; /* t*ln2HI is exact here */
+            lo = t * ln2LO[0];
+        }
+        DMATH_OL_STRICT_ASSIGN(double, x, hi - lo);
+    } else if(hx < 0x3e300000) {           /* when |x|<2**-28 */
+        if(huge + x > one) return one + x; /* trigger inexact */
+    } else
+        k = 0;
+
+    /* x is now in primary range */
+    t = x * x;
+    if(k >= -1021)
+        DMATH_OL_INSERT_WORDS(twopk, 0x3ff00000 + (k * 0x00100000), 0);
+    else
+        DMATH_OL_INSERT_WORDS(twopk, 0x3ff00000 + ((k + 1000) * 0x00100000), 0);
+    c = x - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5))));
+    if(k == 0)
+        return one - ((x * c) / (c - 2.0) - x);
+    else
+        y = one - ((lo - (x * c) / (2.0 - c)) - hi);
+    if(k >= -1021) {
+        if(k == 1024) return y * 2.0 * 0x1p1023;
+        return y * twopk;
+    } else {
+        return y * twopk * twom1000;
+    }
+}
+
+// OpenLibm src/s_exp2.c
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define DMATH_OL_TBLBITS 8
+#define DMATH_OL_TBLSIZE (1 << DMATH_OL_TBLBITS)
+
+static double dmath_ol_exp2(double x) {
+    static const double huge = 0x1p1000, redux = 0x1.8p52 / DMATH_OL_TBLSIZE,
+                        P1 = 0x1.62e42fefa39efp-1, P2 = 0x1.ebfbdff82c575p-3,
+                        P3 = 0x1.c6b08d704a0a6p-5, P4 = 0x1.3b2ab88f70400p-7,
+                        P5 = 0x1.5d88003875c74p-10;
+
+    static volatile double twom1000 = 0x1p-1000;
+
+    static const double tbl[DMATH_OL_TBLSIZE * 2] = {
+        /*	dmath_ol_exp2(z + eps)		eps	*/
+        0x1.6a09e667f3d5dp-1, 0x1.9880p-44,  0x1.6b052fa751744p-1, 0x1.8000p-50,
+        0x1.6c012750bd9fep-1, -0x1.8780p-45, 0x1.6cfdcddd476bfp-1, 0x1.ec00p-46,
+        0x1.6dfb23c651a29p-1, -0x1.8000p-50, 0x1.6ef9298593ae3p-1, -0x1.c000p-52,
+        0x1.6ff7df9519386p-1, -0x1.fd80p-45, 0x1.70f7466f42da3p-1, -0x1.c880p-45,
+        0x1.71f75e8ec5fc3p-1, 0x1.3c00p-46,  0x1.72f8286eacf05p-1, -0x1.8300p-44,
+        0x1.73f9a48a58152p-1, -0x1.0c00p-47, 0x1.74fbd35d7ccfcp-1, 0x1.f880p-45,
+        0x1.75feb564267f1p-1, 0x1.3e00p-47,  0x1.77024b1ab6d48p-1, -0x1.7d00p-45,
+        0x1.780694fde5d38p-1, -0x1.d000p-50, 0x1.790b938ac1d00p-1, 0x1.3000p-49,
+        0x1.7a11473eb0178p-1, -0x1.d000p-49, 0x1.7b17b0976d060p-1, 0x1.0400p-45,
+        0x1.7c1ed0130c133p-1, 0x1.0000p-53,  0x1.7d26a62ff8636p-1, -0x1.6900p-45,
+        0x1.7e2f336cf4e3bp-1, -0x1.2e00p-47, 0x1.7f3878491c3e8p-1, -0x1.4580p-45,
+        0x1.80427543e1b4ep-1, 0x1.3000p-44,  0x1.814d2add1071ap-1, 0x1.f000p-47,
+        0x1.82589994ccd7ep-1, -0x1.1c00p-45, 0x1.8364c1eb942d0p-1, 0x1.9d00p-45,
+        0x1.8471a4623cab5p-1, 0x1.7100p-43,  0x1.857f4179f5bbcp-1, 0x1.2600p-45,
+        0x1.868d99b4491afp-1, -0x1.2c40p-44, 0x1.879cad931a395p-1, -0x1.3000p-45,
+        0x1.88ac7d98a65b8p-1, -0x1.a800p-45, 0x1.89bd0a4785800p-1, -0x1.d000p-49,
+        0x1.8ace5422aa223p-1, 0x1.3280p-44,  0x1.8be05bad619fap-1, 0x1.2b40p-43,
+        0x1.8cf3216b54383p-1, -0x1.ed00p-45, 0x1.8e06a5e08664cp-1, -0x1.0500p-45,
+        0x1.8f1ae99157807p-1, 0x1.8280p-45,  0x1.902fed0282c0ep-1, -0x1.cb00p-46,
+        0x1.9145b0b91ff96p-1, -0x1.5e00p-47, 0x1.925c353aa2ff9p-1, 0x1.5400p-48,
+        0x1.93737b0cdc64ap-1, 0x1.7200p-46,  0x1.948b82b5f98aep-1, -0x1.9000p-47,
+        0x1.95a44cbc852cbp-1, 0x1.5680p-45,  0x1.96bdd9a766f21p-1, -0x1.6d00p-44,
+        0x1.97d829fde4e2ap-1, -0x1.1000p-47, 0x1.98f33e47a23a3p-1, 0x1.d000p-45,
+        0x1.9a0f170ca0604p-1, -0x1.8a40p-44, 0x1.9b2bb4d53ff89p-1, 0x1.55c0p-44,
+        0x1.9c49182a3f15bp-1, 0x1.6b80p-45,  0x1.9d674194bb8c5p-1, -0x1.c000p-49,
+        0x1.9e86319e3238ep-1, 0x1.7d00p-46,  0x1.9fa5e8d07f302p-1, 0x1.6400p-46,
+        0x1.a0c667b5de54dp-1, -0x1.5000p-48, 0x1.a1e7aed8eb8f6p-1, 0x1.9e00p-47,
+        0x1.a309bec4a2e27p-1, 0x1.ad80p-45,  0x1.a42c980460a5dp-1, -0x1.af00p-46,
+        0x1.a5503b23e259bp-1, 0x1.b600p-47,  0x1.a674a8af46213p-1, 0x1.8880p-44,
+        0x1.a799e1330b3a7p-1, 0x1.1200p-46,  0x1.a8bfe53c12e8dp-1, 0x1.6c00p-47,
+        0x1.a9e6b5579fcd2p-1, -0x1.9b80p-45, 0x1.ab0e521356fb8p-1, 0x1.b700p-45,
+        0x1.ac36bbfd3f381p-1, 0x1.9000p-50,  0x1.ad5ff3a3c2780p-1, 0x1.4000p-49,
+        0x1.ae89f995ad2a3p-1, -0x1.c900p-45, 0x1.afb4ce622f367p-1, 0x1.6500p-46,
+        0x1.b0e07298db790p-1, 0x1.fd40p-45,  0x1.b20ce6c9a89a9p-1, 0x1.2700p-46,
+        0x1.b33a2b84f1a4bp-1, 0x1.d470p-43,  0x1.b468415b747e7p-1, -0x1.8380p-44,
+        0x1.b59728de5593ap-1, 0x1.8000p-54,  0x1.b6c6e29f1c56ap-1, 0x1.ad00p-47,
+        0x1.b7f76f2fb5e50p-1, 0x1.e800p-50,  0x1.b928cf22749b2p-1, -0x1.4c00p-47,
+        0x1.ba5b030a10603p-1, -0x1.d700p-47, 0x1.bb8e0b79a6f66p-1, 0x1.d900p-47,
+        0x1.bcc1e904bc1ffp-1, 0x1.2a00p-47,  0x1.bdf69c3f3a16fp-1, -0x1.f780p-46,
+        0x1.bf2c25bd71db8p-1, -0x1.0a00p-46, 0x1.c06286141b2e9p-1, -0x1.1400p-46,
+        0x1.c199bdd8552e0p-1, 0x1.be00p-47,  0x1.c2d1cd9fa64eep-1, -0x1.9400p-47,
+        0x1.c40ab5fffd02fp-1, -0x1.ed00p-47, 0x1.c544778fafd15p-1, 0x1.9660p-44,
+        0x1.c67f12e57d0cbp-1, -0x1.a100p-46, 0x1.c7ba88988c1b6p-1, -0x1.8458p-42,
+        0x1.c8f6d9406e733p-1, -0x1.a480p-46, 0x1.ca3405751c4dfp-1, 0x1.b000p-51,
+        0x1.cb720dcef9094p-1, 0x1.1400p-47,  0x1.ccb0f2e6d1689p-1, 0x1.0200p-48,
+        0x1.cdf0b555dc412p-1, 0x1.3600p-48,  0x1.cf3155b5bab3bp-1, -0x1.6900p-47,
+        0x1.d072d4a0789bcp-1, 0x1.9a00p-47,  0x1.d1b532b08c8fap-1, -0x1.5e00p-46,
+        0x1.d2f87080d8a85p-1, 0x1.d280p-46,  0x1.d43c8eacaa203p-1, 0x1.1a00p-47,
+        0x1.d5818dcfba491p-1, 0x1.f000p-50,  0x1.d6c76e862e6a1p-1, -0x1.3a00p-47,
+        0x1.d80e316c9834ep-1, -0x1.cd80p-47, 0x1.d955d71ff6090p-1, 0x1.4c00p-48,
+        0x1.da9e603db32aep-1, 0x1.f900p-48,  0x1.dbe7cd63a8325p-1, 0x1.9800p-49,
+        0x1.dd321f301b445p-1, -0x1.5200p-48, 0x1.de7d5641c05bfp-1, -0x1.d700p-46,
+        0x1.dfc97337b9aecp-1, -0x1.6140p-46, 0x1.e11676b197d5ep-1, 0x1.b480p-47,
+        0x1.e264614f5a3e7p-1, 0x1.0ce0p-43,  0x1.e3b333b16ee5cp-1, 0x1.c680p-47,
+        0x1.e502ee78b3fb4p-1, -0x1.9300p-47, 0x1.e653924676d68p-1, -0x1.5000p-49,
+        0x1.e7a51fbc74c44p-1, -0x1.7f80p-47, 0x1.e8f7977cdb726p-1, -0x1.3700p-48,
+        0x1.ea4afa2a490e8p-1, 0x1.5d00p-49,  0x1.eb9f4867ccae4p-1, 0x1.61a0p-46,
+        0x1.ecf482d8e680dp-1, 0x1.5500p-48,  0x1.ee4aaa2188514p-1, 0x1.6400p-51,
+        0x1.efa1bee615a13p-1, -0x1.e800p-49, 0x1.f0f9c1cb64106p-1, -0x1.a880p-48,
+        0x1.f252b376bb963p-1, -0x1.c900p-45, 0x1.f3ac948dd7275p-1, 0x1.a000p-53,
+        0x1.f50765b6e4524p-1, -0x1.4f00p-48, 0x1.f6632798844fdp-1, 0x1.a800p-51,
+        0x1.f7bfdad9cbe38p-1, 0x1.abc0p-48,  0x1.f91d802243c82p-1, -0x1.4600p-50,
+        0x1.fa7c1819e908ep-1, -0x1.b0c0p-47, 0x1.fbdba3692d511p-1, -0x1.0e00p-51,
+        0x1.fd3c22b8f7194p-1, -0x1.0de8p-46, 0x1.fe9d96b2a23eep-1, 0x1.e430p-49,
+        0x1.0000000000000p+0, 0x0.0000p+0,   0x1.00b1afa5abcbep+0, -0x1.3400p-52,
+        0x1.0163da9fb3303p+0, -0x1.2170p-46, 0x1.02168143b0282p+0, 0x1.a400p-52,
+        0x1.02c9a3e77806cp+0, 0x1.f980p-49,  0x1.037d42e11bbcap+0, -0x1.7400p-51,
+        0x1.04315e86e7f89p+0, 0x1.8300p-50,  0x1.04e5f72f65467p+0, -0x1.a3f0p-46,
+        0x1.059b0d315855ap+0, -0x1.2840p-47, 0x1.0650a0e3c1f95p+0, 0x1.1600p-48,
+        0x1.0706b29ddf71ap+0, 0x1.5240p-46,  0x1.07bd42b72a82dp+0, -0x1.9a00p-49,
+        0x1.0874518759bd0p+0, 0x1.6400p-49,  0x1.092bdf66607c8p+0, -0x1.0780p-47,
+        0x1.09e3ecac6f383p+0, -0x1.8000p-54, 0x1.0a9c79b1f3930p+0, 0x1.fa00p-48,
+        0x1.0b5586cf988fcp+0, -0x1.ac80p-48, 0x1.0c0f145e46c8ap+0, 0x1.9c00p-50,
+        0x1.0cc922b724816p+0, 0x1.5200p-47,  0x1.0d83b23395dd8p+0, -0x1.ad00p-48,
+        0x1.0e3ec32d3d1f3p+0, 0x1.bac0p-46,  0x1.0efa55fdfa9a6p+0, -0x1.4e80p-47,
+        0x1.0fb66affed2f0p+0, -0x1.d300p-47, 0x1.1073028d7234bp+0, 0x1.1500p-48,
+        0x1.11301d0125b5bp+0, 0x1.c000p-49,  0x1.11edbab5e2af9p+0, 0x1.6bc0p-46,
+        0x1.12abdc06c31d5p+0, 0x1.8400p-49,  0x1.136a814f2047dp+0, -0x1.ed00p-47,
+        0x1.1429aaea92de9p+0, 0x1.8e00p-49,  0x1.14e95934f3138p+0, 0x1.b400p-49,
+        0x1.15a98c8a58e71p+0, 0x1.5300p-47,  0x1.166a45471c3dfp+0, 0x1.3380p-47,
+        0x1.172b83c7d5211p+0, 0x1.8d40p-45,  0x1.17ed48695bb9fp+0, -0x1.5d00p-47,
+        0x1.18af9388c8d93p+0, -0x1.c880p-46, 0x1.1972658375d66p+0, 0x1.1f00p-46,
+        0x1.1a35beb6fcba7p+0, 0x1.0480p-46,  0x1.1af99f81387e3p+0, -0x1.7390p-43,
+        0x1.1bbe084045d54p+0, 0x1.4e40p-45,  0x1.1c82f95281c43p+0, -0x1.a200p-47,
+        0x1.1d4873168b9b2p+0, 0x1.3800p-49,  0x1.1e0e75eb44031p+0, 0x1.ac00p-49,
+        0x1.1ed5022fcd938p+0, 0x1.1900p-47,  0x1.1f9c18438cdf7p+0, -0x1.b780p-46,
+        0x1.2063b88628d8fp+0, 0x1.d940p-45,  0x1.212be3578a81ep+0, 0x1.8000p-50,
+        0x1.21f49917ddd41p+0, 0x1.b340p-45,  0x1.22bdda2791323p+0, 0x1.9f80p-46,
+        0x1.2387a6e7561e7p+0, -0x1.9c80p-46, 0x1.2451ffb821427p+0, 0x1.2300p-47,
+        0x1.251ce4fb2a602p+0, -0x1.3480p-46, 0x1.25e85711eceb0p+0, 0x1.2700p-46,
+        0x1.26b4565e27d16p+0, 0x1.1d00p-46,  0x1.2780e341de00fp+0, 0x1.1ee0p-44,
+        0x1.284dfe1f5633ep+0, -0x1.4c00p-46, 0x1.291ba7591bb30p+0, -0x1.3d80p-46,
+        0x1.29e9df51fdf09p+0, 0x1.8b00p-47,  0x1.2ab8a66d10e9bp+0, -0x1.27c0p-45,
+        0x1.2b87fd0dada3ap+0, 0x1.a340p-45,  0x1.2c57e39771af9p+0, -0x1.0800p-46,
+        0x1.2d285a6e402d9p+0, -0x1.ed00p-47, 0x1.2df961f641579p+0, -0x1.4200p-48,
+        0x1.2ecafa93e2ecfp+0, -0x1.4980p-45, 0x1.2f9d24abd8822p+0, -0x1.6300p-46,
+        0x1.306fe0a31b625p+0, -0x1.2360p-44, 0x1.31432edeea50bp+0, -0x1.0df8p-40,
+        0x1.32170fc4cd7b8p+0, -0x1.2480p-45, 0x1.32eb83ba8e9a2p+0, -0x1.5980p-45,
+        0x1.33c08b2641766p+0, 0x1.ed00p-46,  0x1.3496266e3fa27p+0, -0x1.c000p-50,
+        0x1.356c55f929f0fp+0, -0x1.0d80p-44, 0x1.36431a2de88b9p+0, 0x1.2c80p-45,
+        0x1.371a7373aaa39p+0, 0x1.0600p-45,  0x1.37f26231e74fep+0, -0x1.6600p-46,
+        0x1.38cae6d05d838p+0, -0x1.ae00p-47, 0x1.39a401b713ec3p+0, -0x1.4720p-43,
+        0x1.3a7db34e5a020p+0, 0x1.8200p-47,  0x1.3b57fbfec6e95p+0, 0x1.e800p-44,
+        0x1.3c32dc313a8f2p+0, 0x1.f800p-49,  0x1.3d0e544ede122p+0, -0x1.7a00p-46,
+        0x1.3dea64c1234bbp+0, 0x1.6300p-45,  0x1.3ec70df1c4eccp+0, -0x1.8a60p-43,
+        0x1.3fa4504ac7e8cp+0, -0x1.cdc0p-44, 0x1.40822c367a0bbp+0, 0x1.5b80p-45,
+        0x1.4160a21f72e95p+0, 0x1.ec00p-46,  0x1.423fb27094646p+0, -0x1.3600p-46,
+        0x1.431f5d950a920p+0, 0x1.3980p-45,  0x1.43ffa3f84b9ebp+0, 0x1.a000p-48,
+        0x1.44e0860618919p+0, -0x1.6c00p-48, 0x1.45c2042a7d201p+0, -0x1.bc00p-47,
+        0x1.46a41ed1d0016p+0, -0x1.2800p-46, 0x1.4786d668b3326p+0, 0x1.0e00p-44,
+        0x1.486a2b5c13c00p+0, -0x1.d400p-45, 0x1.494e1e192af04p+0, 0x1.c200p-47,
+        0x1.4a32af0d7d372p+0, -0x1.e500p-46, 0x1.4b17dea6db801p+0, 0x1.7800p-47,
+        0x1.4bfdad53629e1p+0, -0x1.3800p-46, 0x1.4ce41b817c132p+0, 0x1.0800p-47,
+        0x1.4dcb299fddddbp+0, 0x1.c700p-45,  0x1.4eb2d81d8ab96p+0, -0x1.ce00p-46,
+        0x1.4f9b2769d2d02p+0, 0x1.9200p-46,  0x1.508417f4531c1p+0, -0x1.8c00p-47,
+        0x1.516daa2cf662ap+0, -0x1.a000p-48, 0x1.5257de83f51eap+0, 0x1.a080p-43,
+        0x1.5342b569d4edap+0, -0x1.6d80p-45, 0x1.542e2f4f6ac1ap+0, -0x1.2440p-44,
+        0x1.551a4ca5d94dbp+0, 0x1.83c0p-43,  0x1.56070dde9116bp+0, 0x1.4b00p-45,
+        0x1.56f4736b529dep+0, 0x1.15a0p-43,  0x1.57e27dbe2c40ep+0, -0x1.9e00p-45,
+        0x1.58d12d497c76fp+0, -0x1.3080p-45, 0x1.59c0827ff0b4cp+0, 0x1.dec0p-43,
+        0x1.5ab07dd485427p+0, -0x1.4000p-51, 0x1.5ba11fba87af4p+0, 0x1.0080p-44,
+        0x1.5c9268a59460bp+0, -0x1.6c80p-45, 0x1.5d84590998e3fp+0, 0x1.69a0p-43,
+        0x1.5e76f15ad20e1p+0, -0x1.b400p-46, 0x1.5f6a320dcebcap+0, 0x1.7700p-46,
+        0x1.605e1b976dcb8p+0, 0x1.6f80p-45,  0x1.6152ae6cdf715p+0, 0x1.1000p-47,
+        0x1.6247eb03a5531p+0, -0x1.5d00p-46, 0x1.633dd1d1929b5p+0, -0x1.2d00p-46,
+        0x1.6434634ccc313p+0, -0x1.a800p-49, 0x1.652b9febc8efap+0, -0x1.8600p-45,
+        0x1.6623882553397p+0, 0x1.1fe0p-40,  0x1.671c1c708328ep+0, -0x1.7200p-44,
+        0x1.68155d44ca97ep+0, 0x1.6800p-49,  0x1.690f4b19e9471p+0, -0x1.9780p-45,
+    };
+
+    /*
+     * dmath_ol_exp2(x): compute the base 2 exponential of x
+     *
+     * Accuracy: Peak error < 0.503 ulp for normalized results.
+     *
+     * Method: (accurate tables)
+     *
+     *   Reduce x:
+     *     x = 2**k + y, for integer k and |y| <= 1/2.
+     *     Thus we have dmath_ol_exp2(x) = 2**k * dmath_ol_exp2(y).
+     *
+     *   Reduce y:
+     *     y = i/DMATH_OL_TBLSIZE + z - eps[i] for integer i near y * DMATH_OL_TBLSIZE.
+     *     Thus we have dmath_ol_exp2(y) = dmath_ol_exp2(i/DMATH_OL_TBLSIZE) * dmath_ol_exp2(z -
+     *eps[i]), with |z - eps[i]| <= 2**-9 + 2**-39 for the table used.
+     *
+     *   We compute dmath_ol_exp2(i/DMATH_OL_TBLSIZE) via table lookup and dmath_ol_exp2(z - eps[i])
+     *via a degree-5 minimax polynomial with maximum error under 1.3 * 2**-61. The values in exp2t[]
+     *and eps[] are chosen such that exp2t[i] = dmath_ol_exp2(i/DMATH_OL_TBLSIZE + eps[i]), and
+     *eps[i] is a small offset such that exp2t[i] is accurate to 2**-64.
+     *
+     *   Note that the range of i is +-DMATH_OL_TBLSIZE/2, so we actually index the tables
+     *   by i0 = i + DMATH_OL_TBLSIZE/2.  For cache efficiency, exp2t[] and eps[] are
+     *   virtual tables, interleaved in the real table tbl[].
+     *
+     *   This method is due to Gal, with many details due to Gal and Bachelis:
+     *
+     *	Gal, S. and Bachelis, B.  An Accurate Elementary Mathematical Library
+     *	for the IEEE Floating Point Standard.  TOMS 17(1), 26-46 (1991).
+     */
+
+    double r, t, twopk, twopkp1000, z;
+    uint32_t hx, ix, lx, i0;
+    int k;
+
+    /* Filter out exceptional cases. */
+    DMATH_OL_GET_HIGH_WORD(hx, x);
+    ix = hx & 0x7fffffff;  /* high word of |x| */
+    if(ix >= 0x40900000) { /* |x| >= 1024 */
+        if(ix >= 0x7ff00000) {
+            DMATH_OL_GET_LOW_WORD(lx, x);
+            if(((ix & 0xfffff) | lx) != 0 || (hx & 0x80000000) == 0)
+                return (x + x); /* x is NaN or +Inf */
+            else
+                return (0.0); /* x is -Inf */
+        }
+        if(x >= 0x1.0p10) return (huge * huge);            /* overflow */
+        if(x <= -0x1.0ccp10) return (twom1000 * twom1000); /* underflow */
+    } else if(ix < 0x3c900000) {                           /* |x| < 0x1p-54 */
+        return (1.0 + x);
+    }
+
+    /* Reduce x, computing z, i0, and k. */
+    DMATH_OL_STRICT_ASSIGN(double, t, x + redux);
+    DMATH_OL_GET_LOW_WORD(i0, t);
+    i0 += DMATH_OL_TBLSIZE / 2;
+    k = dmath_ol_i32((i0 >> DMATH_OL_TBLBITS) << 20);
+    i0 = (i0 & (DMATH_OL_TBLSIZE - 1)) << 1;
+    t -= redux;
+    z = x - t;
+
+    /* Compute r = dmath_ol_exp2(y) = exp2t[i0] * p(z - eps[i]). */
+    t = tbl[i0];      /* exp2t[i0] */
+    z -= tbl[i0 + 1]; /* eps[i0]   */
+    if(k >= -(1021 << 20))
+        DMATH_OL_INSERT_WORDS(twopk, 0x3ff00000 + k, 0);
+    else
+        DMATH_OL_INSERT_WORDS(twopkp1000, 0x3ff00000 + k + (1000 << 20), 0);
+    r = t + t * z * (P1 + z * (P2 + z * (P3 + z * (P4 + z * P5))));
+
+    /* Scale by 2**(k>>20). */
+    if(k >= -(1021 << 20)) {
+        if(k == 1024 << 20) return (r * 2.0 * 0x1p1023);
+        return (r * twopk);
+    } else {
+        return (r * twopkp1000 * twom1000);
+    }
+}
+
+#undef DMATH_OL_TBLBITS
+#undef DMATH_OL_TBLSIZE
+
+// OpenLibm src/e_log.c
+/* @(#)e_log.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* dmath_ol_log(x)
+ * Return the logrithm of x
+ *
+ * Method :
+ *   1. Argument Reduction: find k and f such that
+ *			x = 2^k * (1+f),
+ *	   where  dmath_sqrt(2)/2 < 1+f < dmath_sqrt(2) .
+ *
+ *   2. Approximation of log(1+f).
+ *	Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
+ *		 = 2s + 2/3 s**3 + 2/5 s**5 + .....,
+ *	     	 = 2s + s*R
+ *      We use a special Reme algorithm on [0,0.1716] to generate
+ * 	a polynomial of degree 14 to approximate R The maximum error
+ *	of this polynomial approximation is bounded by 2**-58.45. In
+ *	other words,
+ *		        2      4      6      8      10      12      14
+ *	    R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s  +Lg6*s  +Lg7*s
+ *  	(the values of Lg1 to Lg7 are listed in the program)
+ *	and
+ *	    |      2          14          |     -58.45
+ *	    | Lg1*s +...+Lg7*s    -  R(z) | <= 2
+ *	    |                             |
+ *	Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
+ *	In order to guarantee error in log below 1ulp, we compute log
+ *	by
+ *		log(1+f) = f - s*(f - R)	(if f is not too large)
+ *		log(1+f) = f - (hfsq - s*(hfsq+R)).	(better accuracy)
+ *
+ *	3. Finally,  log(x) = k*ln2 + log(1+f).
+ *			    = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
+ *	   Here ln2 is split into two floating point number:
+ *			ln2_hi + ln2_lo,
+ *	   where n*ln2_hi is always exact for |n| < 2000.
+ *
+ * Special cases:
+ *	log(x) is NaN with signal if x < 0 (including -INF) ;
+ *	log(+INF) is +INF; log(0) is -INF with signal;
+ *	log(NaN) is that NaN with no signal.
+ *
+ * Accuracy:
+ *	according to an error analysis, the error is always less than
+ *	1 ulp (unit in the last place).
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+static double dmath_ol_log(double x) {
+    static const double ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */
+        ln2_lo = 1.90821492927058770002e-10,                 /* 3dea39ef 35793c76 */
+        two54 = 1.80143985094819840000e+16,                  /* 43500000 00000000 */
+        Lg1 = 6.666666666666735130e-01,                      /* 3FE55555 55555593 */
+        Lg2 = 3.999999999940941908e-01,                      /* 3FD99999 9997FA04 */
+        Lg3 = 2.857142874366239149e-01,                      /* 3FD24924 94229359 */
+        Lg4 = 2.222219843214978396e-01,                      /* 3FCC71C5 1D8E78AF */
+        Lg5 = 1.818357216161805012e-01,                      /* 3FC74664 96CB03DE */
+        Lg6 = 1.531383769920937332e-01,                      /* 3FC39A09 D078C69F */
+        Lg7 = 1.479819860511658591e-01;                      /* 3FC2F112 DF3E5244 */
+
+    static const double zero = 0.0;
+
+    double hfsq, f, s, z, R, w, t1, t2, dk;
+    int32_t k, hx, i, j;
+    uint32_t lx;
+
+    DMATH_OL_EXTRACT_WORDS(hx, lx, x);
+
+    k = 0;
+    if(hx < 0x00100000) {                                       /* x < 2**-1022  */
+        if(((hx & 0x7fffffff) | lx) == 0) return -two54 / zero; /* log(+-0)=-inf */
+        if(hx < 0) return (x - x) / zero;                       /* log(-#) = NaN */
+        k -= 54;
+        x *= two54; /* subnormal number, scale up x */
+        DMATH_OL_GET_HIGH_WORD(hx, x);
+    }
+    if(hx >= 0x7ff00000) return x + x;
+    k += (hx >> 20) - 1023;
+    hx &= 0x000fffff;
+    i = (hx + 0x95f64) & 0x100000;
+    DMATH_OL_SET_HIGH_WORD(x, hx | (i ^ 0x3ff00000)); /* normalize x or x/2 */
+    k += (i >> 20);
+    f = x - 1.0;
+    if((0x000fffff & (2 + hx)) < 3) { /* -2**-20 <= f < 2**-20 */
+        if(f == zero) {
+            if(k == 0) {
+                return zero;
+            } else {
+                dk = (double)k;
+                return dk * ln2_hi + dk * ln2_lo;
+            }
+        }
+        R = f * f * (0.5 - 0.33333333333333333 * f);
+        if(k == 0)
+            return f - R;
+        else {
+            dk = (double)k;
+            return dk * ln2_hi - ((R - dk * ln2_lo) - f);
+        }
+    }
+    s = f / (2.0 + f);
+    dk = (double)k;
+    z = s * s;
+    i = hx - 0x6147a;
+    w = z * z;
+    j = 0x6b851 - hx;
+    t1 = w * (Lg2 + w * (Lg4 + w * Lg6));
+    t2 = z * (Lg1 + w * (Lg3 + w * (Lg5 + w * Lg7)));
+    i |= j;
+    R = t2 + t1;
+    if(i > 0) {
+        hfsq = 0.5 * f * f;
+        if(k == 0)
+            return f - (hfsq - s * (hfsq + R));
+        else
+            return dk * ln2_hi - ((hfsq - (s * (hfsq + R) + dk * ln2_lo)) - f);
+    } else {
+        if(k == 0)
+            return f - s * (f - R);
+        else
+            return dk * ln2_hi - ((s * (f - R) - dk * ln2_lo) - f);
+    }
+}
+
+// OpenLibm src/e_log2.c
+/* @(#)e_log10.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * Return the base 2 logarithm of x.  See e_log.c and k_log.h for most
+ * comments.
+ *
+ * This reduces x to {k, 1+f} exactly as in e_log.c, then calls the kernel,
+ * then does the combining and scaling steps
+ *    log2(x) = (f - 0.5*f*f + dmath_ol_log1p_kernel(f)) / ln2 + k
+ * in not-quite-routine extra precision.
+ */
+
+static double dmath_ol_log2(double x) {
+    static const double two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
+        ivln2hi = 1.44269504072144627571e+00,               /* 0x3ff71547, 0x65200000 */
+        ivln2lo = 1.67517131648865118353e-10;               /* 0x3de705fc, 0x2eefa200 */
+
+    static const double zero = 0.0;
+
+    double f, hfsq, hi, lo, r, val_hi, val_lo, w, y;
+    int32_t i, k, hx;
+    uint32_t lx;
+
+    DMATH_OL_EXTRACT_WORDS(hx, lx, x);
+
+    k = 0;
+    if(hx < 0x00100000) {                                       /* x < 2**-1022  */
+        if(((hx & 0x7fffffff) | lx) == 0) return -two54 / zero; /* log(+-0)=-inf */
+        if(hx < 0) return (x - x) / zero;                       /* log(-#) = NaN */
+        k -= 54;
+        x *= two54; /* subnormal number, scale up x */
+        DMATH_OL_GET_HIGH_WORD(hx, x);
+    }
+    if(hx >= 0x7ff00000) return x + x;
+    if(hx == 0x3ff00000 && lx == 0) return zero; /* log(1) = +0 */
+    k += (hx >> 20) - 1023;
+    hx &= 0x000fffff;
+    i = (hx + 0x95f64) & 0x100000;
+    DMATH_OL_SET_HIGH_WORD(x, hx | (i ^ 0x3ff00000)); /* normalize x or x/2 */
+    k += (i >> 20);
+    y = (double)k;
+    f = x - 1.0;
+    hfsq = 0.5 * f * f;
+    r = dmath_ol_log1p_kernel(f);
+
+    /*
+     * f-hfsq must (for args near 1) be evaluated in extra precision
+     * to avoid a large cancellation when x is near dmath_sqrt(2) or 1/dmath_sqrt(2).
+     * This is fairly efficient since f-hfsq only depends on f, so can
+     * be evaluated in parallel with R.  Not combining hfsq with R also
+     * keeps R small (though not as small as a true `lo' term would be),
+     * so that extra precision is not needed for terms involving R.
+     *
+     * Compiler bugs involving extra precision used to break Dekker's
+     * theorem for spitting f-hfsq as hi+lo, unless double_t was used
+     * or the multi-precision calculations were avoided when double_t
+     * has extra precision.  These problems are now automatically
+     * avoided as a side effect of the optimization of combining the
+     * Dekker splitting step with the clear-low-bits step.
+     *
+     * y must (for args near dmath_sqrt(2) and 1/dmath_sqrt(2)) be added in extra
+     * precision to avoid a very large cancellation when x is very near
+     * these values.  Unlike the above cancellations, this problem is
+     * specific to base 2.  It is strange that adding +-1 is so much
+     * harder than adding +-ln2 or +-log10_2.
+     *
+     * This uses Dekker's theorem to normalize y+val_hi, so the
+     * compiler bugs are back in some configurations, sigh.  And I
+     * don't want to used double_t to avoid them, since that gives a
+     * pessimization and the support for avoiding the pessimization
+     * is not yet available.
+     *
+     * The multi-precision calculations for the multiplications are
+     * routine.
+     */
+    hi = f - hfsq;
+    DMATH_OL_SET_LOW_WORD(hi, 0);
+    lo = (f - hi) - hfsq + r;
+    val_hi = hi * ivln2hi;
+    val_lo = (lo + hi) * ivln2lo + lo * ivln2hi;
+
+    /* spadd(val_hi, val_lo, y), except for not using double_t: */
+    w = y + val_hi;
+    val_lo += (y - w) + val_hi;
+    val_hi = w;
+
+    return val_lo + val_hi;
+}
+
+// OpenLibm src/e_log10.c
+/* @(#)e_log10.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * Return the base 10 logarithm of x.  See e_log.c and k_log.h for most
+ * comments.
+ *
+ *    log10(x) = (f - 0.5*f*f + dmath_ol_log1p_kernel(f)) / ln10 + k * log10(2)
+ * in not-quite-routine extra precision.
+ */
+
+static double dmath_ol_log10(double x) {
+    static const double two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
+        ivln10hi = 4.34294481878168880939e-01,              /* 0x3fdbcb7b, 0x15200000 */
+        ivln10lo = 2.50829467116452752298e-11,              /* 0x3dbb9438, 0xca9aadd5 */
+        log10_2hi = 3.01029995663611771306e-01,             /* 0x3FD34413, 0x509F6000 */
+        log10_2lo = 3.69423907715893078616e-13;             /* 0x3D59FEF3, 0x11F12B36 */
+
+    static const double zero = 0.0;
+
+    double f, hfsq, hi, lo, r, val_hi, val_lo, w, y, y2;
+    int32_t i, k, hx;
+    uint32_t lx;
+
+    DMATH_OL_EXTRACT_WORDS(hx, lx, x);
+
+    k = 0;
+    if(hx < 0x00100000) {                                       /* x < 2**-1022  */
+        if(((hx & 0x7fffffff) | lx) == 0) return -two54 / zero; /* log(+-0)=-inf */
+        if(hx < 0) return (x - x) / zero;                       /* log(-#) = NaN */
+        k -= 54;
+        x *= two54; /* subnormal number, scale up x */
+        DMATH_OL_GET_HIGH_WORD(hx, x);
+    }
+    if(hx >= 0x7ff00000) return x + x;
+    if(hx == 0x3ff00000 && lx == 0) return zero; /* log(1) = +0 */
+    k += (hx >> 20) - 1023;
+    hx &= 0x000fffff;
+    i = (hx + 0x95f64) & 0x100000;
+    DMATH_OL_SET_HIGH_WORD(x, hx | (i ^ 0x3ff00000)); /* normalize x or x/2 */
+    k += (i >> 20);
+    y = (double)k;
+    f = x - 1.0;
+    hfsq = 0.5 * f * f;
+    r = dmath_ol_log1p_kernel(f);
+
+    /* See e_log2.c for most details. */
+    hi = f - hfsq;
+    DMATH_OL_SET_LOW_WORD(hi, 0);
+    lo = (f - hi) - hfsq + r;
+    val_hi = hi * ivln10hi;
+    y2 = y * log10_2hi;
+    val_lo = y * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi;
+
+    /*
+     * Extra precision in for adding y*log10_2hi is not strictly needed
+     * since there is no very large cancellation near x = dmath_sqrt(2) or
+     * x = 1/dmath_sqrt(2), but we do it anyway since it costs little on CPUs
+     * with some parallelism and it reduces the error for many args.
+     */
+    w = y2 + val_hi;
+    val_lo += (y2 - w) + val_hi;
+    val_hi = w;
+
+    return val_lo + val_hi;
+}
+
+// OpenLibm src/e_pow.c
+/* @(#)e_pow.c 1.5 04/04/22 SMI */
+/*
+ * ====================================================
+ * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* dmath_ol_pow(x,y) return x**y
+ *
+ *		      n
+ * Method:  Let x =  2   * (1+f)
+ *	1. Compute and return log2(x) in two pieces:
+ *		log2(x) = w1 + w2,
+ *	   where w1 has 53-24 = 29 bit trailing zeros.
+ *	2. Perform y*log2(x) = n+y' by simulating muti-precision
+ *	   arithmetic, where |y'|<=0.5.
+ *	3. Return x**y = 2**n*exp(y'*log2)
+ *
+ * Special cases:
+ *	1.  (anything) ** 0  is 1
+ *	2.  (anything) ** 1  is itself
+ *	3.  (anything) ** NAN is NAN
+ *	4.  NAN ** (anything except 0) is NAN
+ *	5.  +-(|x| > 1) **  +INF is +INF
+ *	6.  +-(|x| > 1) **  -INF is +0
+ *	7.  +-(|x| < 1) **  +INF is +0
+ *	8.  +-(|x| < 1) **  -INF is +INF
+ *	9.  +-1         ** +-INF is 1
+ *	10. +0 ** (+anything except 0, NAN)               is +0
+ *	11. -0 ** (+anything except 0, NAN, odd integer)  is +0
+ *	12. +0 ** (-anything except 0, NAN)               is +INF
+ *	13. -0 ** (-anything except 0, NAN, odd integer)  is +INF
+ *	14. -0 ** (odd integer) = -( +0 ** (odd integer) )
+ *	15. +INF ** (+anything except 0,NAN) is +INF
+ *	16. +INF ** (-anything except 0,NAN) is +0
+ *	17. -INF ** (anything)  = -0 ** (-anything)
+ *	18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer)
+ *	19. (-anything except 0 and inf) ** (non-integer) is NAN
+ *
+ * Accuracy:
+ *	pow(x,y) returns x**y nearly rounded. In particular
+ *			pow(integer,integer)
+ *	always returns the correct integer provided it is
+ *	representable.
+ *
+ * Constants :
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+static double dmath_ol_pow(double x, double y) {
+    static const double bp[] =
+        {
+            1.0,
+            1.5,
+        },
+                        dp_h[] =
+                            {
+                                0.0,
+                                5.84962487220764160156e-01,
+                            }, /* 0x3FE2B803, 0x40000000 */
+        dp_l[] =
+            {
+                0.0,
+                1.35003920212974897128e-08,
+            },                                                        /* 0x3E4CFDEB, 0x43CFD006 */
+        zero = 0.0, one = 1.0, two = 2.0, two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */
+        huge = 1.0e300, tiny = 1.0e-300,
+                        /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */
+        L1 = 5.99999999999994648725e-01,      /* 0x3FE33333, 0x33333303 */
+        L2 = 4.28571428578550184252e-01,      /* 0x3FDB6DB6, 0xDB6FABFF */
+        L3 = 3.33333329818377432918e-01,      /* 0x3FD55555, 0x518F264D */
+        L4 = 2.72728123808534006489e-01,      /* 0x3FD17460, 0xA91D4101 */
+        L5 = 2.30660745775561754067e-01,      /* 0x3FCD864A, 0x93C9DB65 */
+        L6 = 2.06975017800338417784e-01,      /* 0x3FCA7E28, 0x4A454EEF */
+        P1 = 1.66666666666666019037e-01,      /* 0x3FC55555, 0x5555553E */
+        P2 = -2.77777777770155933842e-03,     /* 0xBF66C16C, 0x16BEBD93 */
+        P3 = 6.61375632143793436117e-05,      /* 0x3F11566A, 0xAF25DE2C */
+        P4 = -1.65339022054652515390e-06,     /* 0xBEBBBD41, 0xC5D26BF1 */
+        P5 = 4.13813679705723846039e-08,      /* 0x3E663769, 0x72BEA4D0 */
+        lg2 = 6.93147180559945286227e-01,     /* 0x3FE62E42, 0xFEFA39EF */
+        lg2_h = 6.93147182464599609375e-01,   /* 0x3FE62E43, 0x00000000 */
+        lg2_l = -1.90465429995776804525e-09,  /* 0xBE205C61, 0x0CA86C39 */
+        ovt = 8.0085662595372944372e-0017,    /* -(1024-log2(ovfl+.5ulp)) */
+        cp = 9.61796693925975554329e-01,      /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */
+        cp_h = 9.61796700954437255859e-01,    /* 0x3FEEC709, 0xE0000000 =(float)cp */
+        cp_l = -7.02846165095275826516e-09,   /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/
+        ivln2 = 1.44269504088896338700e+00,   /* 0x3FF71547, 0x652B82FE =1/ln2 */
+        ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/
+        ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/
+
+    double z, ax, z_h, z_l, p_h, p_l;
+    double y1, t1, t2, r, s, t, u, v, w;
+    int32_t i, j, k, yisint, n;
+    int32_t hx, hy, ix, iy;
+    uint32_t lx, ly;
+
+    DMATH_OL_EXTRACT_WORDS(hx, lx, x);
+    DMATH_OL_EXTRACT_WORDS(hy, ly, y);
+    ix = hx & 0x7fffffff;
+    iy = hy & 0x7fffffff;
+
+    /* y==zero: x**0 = 1 */
+    if((iy | ly) == 0) return one;
+
+    /* x==1: 1**y = 1, even if y is NaN */
+    if(hx == 0x3ff00000 && lx == 0) return one;
+
+    /* y!=zero: result is NaN if either arg is NaN */
+    if(ix > 0x7ff00000 || ((ix == 0x7ff00000) && (lx != 0)) || iy > 0x7ff00000 ||
+       ((iy == 0x7ff00000) && (ly != 0)))
+        return (x + 0.0) + (y + 0.0);
+
+    /* determine if y is an odd int when x < 0
+     * yisint = 0	... y is not an integer
+     * yisint = 1	... y is an odd int
+     * yisint = 2	... y is an even int
+     */
+    yisint = 0;
+    if(hx < 0) {
+        if(iy >= 0x43400000)
+            yisint = 2; /* even integer y */
+        else if(iy >= 0x3ff00000) {
+            k = (iy >> 20) - 0x3ff; /* exponent */
+            if(k > 20) {
+                j = dmath_ol_i32(ly >> (52 - k));
+                if(((uint32_t)j << (52 - k)) == ly) yisint = 2 - (j & 1);
+            } else if(ly == 0) {
+                j = iy >> (20 - k);
+                if((j << (20 - k)) == iy) yisint = 2 - (j & 1);
+            }
+        }
+    }
+
+    /* special value of y */
+    if(ly == 0) {
+        if(iy == 0x7ff00000) { /* y is +-inf */
+            if(((ix - 0x3ff00000) | lx) == 0)
+                return one;           /* (-1)**+-inf is 1 */
+            else if(ix >= 0x3ff00000) /* (|x|>1)**+-inf = inf,0 */
+                return (hy >= 0) ? y : zero;
+            else /* (|x|<1)**-,+inf = inf,0 */
+                return (hy < 0) ? -y : zero;
+        }
+        if(iy == 0x3ff00000) { /* y is  +-1 */
+            if(hy < 0)
+                return one / x;
+            else
+                return x;
+        }
+        if(hy == 0x40000000) return x * x;     /* y is  2 */
+        if(hy == 0x40080000) return x * x * x; /* y is  3 */
+        if(hy == 0x40100000) {                 /* y is  4 */
+            u = x * x;
+            return u * u;
+        }
+        if(hy == 0x3fe00000) { /* y is  0.5 */
+            if(hx >= 0)        /* x >= +0 */
+                return dmath_sqrt(x);
+        }
+    }
+
+    ax = dmath_fabs(x);
+    /* special value of x */
+    if(lx == 0) {
+        if(ix == 0x7ff00000 || ix == 0 || ix == 0x3ff00000) {
+            z = ax;                 /*x is +-0,+-inf,+-1*/
+            if(hy < 0) z = one / z; /* z = (1/|x|) */
+            if(hx < 0) {
+                if(((ix - 0x3ff00000) | yisint) == 0) {
+                    z = (z - z) / (z - z); /* (-1)**non-int is NaN */
+                } else if(yisint == 1)
+                    z = -z; /* (x<0)**odd = -(|x|**odd) */
+            }
+            return z;
+        }
+    }
+
+    /* CYGNUS LOCAL + fdlibm-5.3 fix: This used to be
+        n = (hx>>31)+1;
+       but ANSI C says a right shift of a signed negative quantity is
+       implementation defined.  */
+    n = (int32_t)((uint32_t)hx >> 31) - 1;
+
+    /* (x<0)**(non-int) is NaN */
+    if((n | yisint) == 0) return (x - x) / (x - x);
+
+    s = one;                              /* s (sign of result -ve**odd) = -1 else = 1 */
+    if((n | (yisint - 1)) == 0) s = -one; /* (-ve)**(odd int) */
+
+    /* |y| is huge */
+    if(iy > 0x41e00000) {     /* if |y| > 2**31 */
+        if(iy > 0x43f00000) { /* if |y| > 2**64, must o/uflow */
+            if(ix <= 0x3fefffff) return (hy < 0) ? huge * huge : tiny * tiny;
+            if(ix >= 0x3ff00000) return (hy > 0) ? huge * huge : tiny * tiny;
+        }
+        /* over/underflow if x is not close to one */
+        if(ix < 0x3fefffff) return (hy < 0) ? s * huge * huge : s * tiny * tiny;
+        if(ix > 0x3ff00000) return (hy > 0) ? s * huge * huge : s * tiny * tiny;
+        /* now |1-x| is tiny <= 2**-20, suffice to compute
+           log(x) by x-x^2/2+x^3/3-x^4/4 */
+        t = ax - one; /* t has 20 trailing zeros */
+        w = (t * t) * (0.5 - t * (0.3333333333333333333333 - t * 0.25));
+        u = ivln2_h * t; /* ivln2_h has 21 sig. bits */
+        v = t * ivln2_l - w * ivln2;
+        t1 = u + v;
+        DMATH_OL_SET_LOW_WORD(t1, 0);
+        t2 = v - (t1 - u);
+    } else {
+        double ss, s2, s_h, s_l, t_h, t_l;
+        n = 0;
+        /* take care subnormal number */
+        if(ix < 0x00100000) {
+            ax *= two53;
+            n -= 53;
+            DMATH_OL_GET_HIGH_WORD(ix, ax);
+        }
+        n += ((ix) >> 20) - 0x3ff;
+        j = ix & 0x000fffff;
+        /* determine interval */
+        ix = j | 0x3ff00000; /* normalize ix */
+        if(j <= 0x3988E)
+            k = 0; /* |x|<dmath_sqrt(3/2) */
+        else if(j < 0xBB67A)
+            k = 1; /* |x|<dmath_sqrt(3)   */
+        else {
+            k = 0;
+            n += 1;
+            ix -= 0x00100000;
+        }
+        DMATH_OL_SET_HIGH_WORD(ax, ix);
+
+        /* compute ss = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
+        u = ax - bp[k]; /* bp[0]=1.0, bp[1]=1.5 */
+        v = one / (ax + bp[k]);
+        ss = u * v;
+        s_h = ss;
+        DMATH_OL_SET_LOW_WORD(s_h, 0);
+        /* t_h=ax+bp[k] High */
+        t_h = zero;
+        DMATH_OL_SET_HIGH_WORD(t_h, ((ix >> 1) | 0x20000000) + 0x00080000 + (k << 18));
+        t_l = ax - (t_h - bp[k]);
+        s_l = v * ((u - s_h * t_h) - s_h * t_l);
+        /* compute log(ax) */
+        s2 = ss * ss;
+        r = s2 * s2 * (L1 + s2 * (L2 + s2 * (L3 + s2 * (L4 + s2 * (L5 + s2 * L6)))));
+        r += s_l * (s_h + ss);
+        s2 = s_h * s_h;
+        t_h = 3.0 + s2 + r;
+        DMATH_OL_SET_LOW_WORD(t_h, 0);
+        t_l = r - ((t_h - 3.0) - s2);
+        /* u+v = ss*(1+...) */
+        u = s_h * t_h;
+        v = s_l * t_h + t_l * ss;
+        /* 2/(3log2)*(ss+...) */
+        p_h = u + v;
+        DMATH_OL_SET_LOW_WORD(p_h, 0);
+        p_l = v - (p_h - u);
+        z_h = cp_h * p_h; /* cp_h+cp_l = 2/(3*log2) */
+        z_l = cp_l * p_h + p_l * cp + dp_l[k];
+        /* log2(ax) = (ss+..)*2/(3*log2) = n + dp_h + z_h + z_l */
+        t = (double)n;
+        t1 = (((z_h + z_l) + dp_h[k]) + t);
+        DMATH_OL_SET_LOW_WORD(t1, 0);
+        t2 = z_l - (((t1 - t) - dp_h[k]) - z_h);
+    }
+
+    /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
+    y1 = y;
+    DMATH_OL_SET_LOW_WORD(y1, 0);
+    p_l = (y - y1) * t1 + y * t2;
+    p_h = y1 * t1;
+    z = p_l + p_h;
+    DMATH_OL_EXTRACT_WORDS(j, i, z);
+    if(j >= 0x40900000) {               /* z >= 1024 */
+        if(((j - 0x40900000) | i) != 0) /* if z > 1024 */
+            return s * huge * huge;     /* overflow */
+        else {
+            if(p_l + ovt > z - p_h) return s * huge * huge; /* overflow */
+        }
+    } else if((j & 0x7fffffff) >= 0x4090cc00) { /* z <= -1075 */
+        if(((j - 0xc090cc00) | i) != 0)         /* z < -1075 */
+            return s * tiny * tiny;             /* underflow */
+        else {
+            if(p_l <= z - p_h) return s * tiny * tiny; /* underflow */
+        }
+    }
+    /*
+     * compute 2**(p_h+p_l)
+     */
+    i = j & 0x7fffffff;
+    k = (i >> 20) - 0x3ff;
+    n = 0;
+    if(i > 0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */
+        n = j + (0x00100000 >> (k + 1));
+        k = ((n & 0x7fffffff) >> 20) - 0x3ff; /* new k for n */
+        t = zero;
+        DMATH_OL_SET_HIGH_WORD(t, n & ~(0x000fffff >> k));
+        n = ((n & 0x000fffff) | 0x00100000) >> (20 - k);
+        if(j < 0) n = -n;
+        p_h -= t;
+    }
+    t = p_l + p_h;
+    DMATH_OL_SET_LOW_WORD(t, 0);
+    u = t * lg2_h;
+    v = (p_l - (t - p_h)) * lg2 + t * lg2_l;
+    z = u + v;
+    w = v - (z - u);
+    t = z * z;
+    t1 = z - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5))));
+    r = (z * t1) / (t1 - two) - (w + z * w);
+    z = one - (r - z);
+    DMATH_OL_GET_HIGH_WORD(j, z);
+    j += n * 0x00100000;
+    if(j < 0x00100000)
+        z = dmath_ol_scalbn(z, n); /* subnormal output */
+    else
+        DMATH_OL_SET_HIGH_WORD(z, j);
+    return s * z;
+}
+
+// OpenLibm src/s_ceil.c (binary64 bit-mask adaptation)
+/* @(#)s_ceil.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+// Use a single uint64_t instead of upstream's high/low 32-bit words. These
+// rounding kernels avoid floating-to-integer casts and omit inexact-flag operations.
+static double dmath_ol_ceil(double x) {
+    uint64_t u = dmath_ol_bits(x);
+    int e = (int)((u >> 52) & 0x7ff) - 1023;
+    if(e >= 52) return x;
+    if(e < 0) {
+        if((u << 1) == 0) return x;
+        return (u >> 63) ? dmath_ol_from_bits(UINT64_C(0x8000000000000000)) : 1.0;
+    }
+    uint64_t mask = (UINT64_C(1) << (52 - e)) - 1;
+    if((u & mask) == 0) return x;
+    if(!(u >> 63)) u += mask;
+    return dmath_ol_from_bits(u & ~mask);
+}
+
+// OpenLibm src/s_floor.c (binary64 bit-mask adaptation)
+/* @(#)s_floor.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+static double dmath_ol_floor(double x) {
+    uint64_t u = dmath_ol_bits(x);
+    int e = (int)((u >> 52) & 0x7ff) - 1023;
+    if(e >= 52) return x;
+    if(e < 0) {
+        if((u << 1) == 0) return x;
+        return (u >> 63) ? -1.0 : 0.0;
+    }
+    uint64_t mask = (UINT64_C(1) << (52 - e)) - 1;
+    if((u & mask) == 0) return x;
+    if(u >> 63) u += mask;
+    return dmath_ol_from_bits(u & ~mask);
+}
+
+// OpenLibm src/s_trunc.c (binary64 bit-mask adaptation)
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+static double dmath_ol_trunc(double x) {
+    uint64_t u = dmath_ol_bits(x);
+    int e = (int)((u >> 52) & 0x7ff) - 1023;
+    if(e >= 52) return x;
+    if(e < 0) return dmath_ol_from_bits(u & UINT64_C(0x8000000000000000));
+    uint64_t mask = (UINT64_C(1) << (52 - e)) - 1;
+    return dmath_ol_from_bits(u & ~mask);
+}
+
+double dmath_ceil(double x) { return dmath_ol_result(dmath_ol_ceil(x)); }
+
+double dmath_floor(double x) { return dmath_ol_result(dmath_ol_floor(x)); }
+
+double dmath_trunc(double x) { return dmath_ol_result(dmath_ol_trunc(x)); }
+
+// OpenLibm src/k_rem_pio2.c
+/* @(#)k_rem_pio2.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * Binary64-only specialization of dmath_ol_kernel_rem_pio2 (upstream prec = 1).
+ * x holds up to three positive 24-bit chunks; e0 is in [-3, 1000].
+ * Return N modulo 8 and a two-double remainder y[0] + y[1] = x - N*pi/2.
+ * The 24-bit chunks of 2/pi let us skip the large integer part of the
+ * product while retaining the low quotient bits and an accurate remainder.
+ * Adaptive recomputation retains additional chunks near multiples of pi/2.
+ */
+
+/*
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+/*
+ * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
+ *
+ *		integer array, contains the (24*i)-th to (24*i+23)-th
+ *		bit of 2/pi after binary point. The corresponding
+ *		floating value is
+ *
+ *			ipio2[i] * 2^(-24(i+1)).
+ *
+ * The first 66 words cover the complete binary64 exponent range.
+ */
+static int dmath_ol_kernel_rem_pio2(double* x, double* y, int e0, int nx) {
+    static const int32_t ipio2[] = {
+        0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, 0x95993C, 0x439041, 0xFE5163,
+        0xABDEBB, 0xC561B7, 0x246E3A, 0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129,
+        0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41, 0x3991D6, 0x398353, 0x39F49C,
+        0x845F8B, 0xBDF928, 0x3B1FF8, 0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF,
+        0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, 0xF17B3D, 0x0739F7, 0x8A5292,
+        0xEA6BFB, 0x5FB11F, 0x8D5D08, 0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3,
+        0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, 0x4D7327, 0x310606, 0x1556CA,
+        0x73A8C9, 0x60E27B, 0xC08C6B,
+
+    };
+
+    static const double PIo2[] = {
+        1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */
+        7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */
+        5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */
+        3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */
+        1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */
+        1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */
+        2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */
+        2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */
+    };
+
+    static const double zero = 0.0, one = 1.0,
+                        two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
+        twon24 = 5.96046447753906250000e-08;                /* 0x3E700000, 0x00000000 */
+
+    int32_t jz, jx, jv, jp, jk, carry, n, iq[20], i, j, k, m, q0, ih;
+    double z, fw, f[20], fq[20], q[20];
+
+    /* initialize jk*/
+    jk = 4; /* binary64 precision */
+    jp = jk;
+
+    /* determine jx,jv,q0, note that 3>q0 */
+    jx = nx - 1;
+    jv = (e0 - 3) / 24;
+    if(jv < 0) jv = 0;
+    q0 = e0 - 24 * (jv + 1);
+
+    /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
+    j = jv - jx;
+    m = jx + jk;
+    for(i = 0; i <= m; i++, j++)
+        f[i] = (j < 0) ? zero : (double)ipio2[j];
+
+    /* compute q[0],q[1],...q[jk] */
+    for(i = 0; i <= jk; i++) {
+        for(j = 0, fw = 0.0; j <= jx; j++)
+            fw += x[j] * f[jx + i - j];
+        q[i] = fw;
+    }
+
+    jz = jk;
+recompute:
+    /* distill q[] into iq[] reversingly */
+    for(i = 0, j = jz, z = q[jz]; j > 0; i++, j--) {
+        fw = (double)((int32_t)(twon24 * z));
+        iq[i] = (int32_t)(z - two24 * fw);
+        z = q[j - 1] + fw;
+    }
+
+    /* compute n */
+    z = dmath_ol_scalbn(z, q0);           /* actual value of z */
+    z -= 8.0 * dmath_ol_floor(z * 0.125); /* trim off integer >= 8 */
+    n = (int32_t)z;
+    z -= (double)n;
+    ih = 0;
+    if(q0 > 0) { /* need iq[jz-1] to determine n */
+        i = (iq[jz - 1] >> (24 - q0));
+        n += i;
+        iq[jz - 1] -= i << (24 - q0);
+        ih = iq[jz - 1] >> (23 - q0);
+    } else if(q0 == 0)
+        ih = iq[jz - 1] >> 23;
+    else if(z >= 0.5)
+        ih = 2;
+
+    if(ih > 0) { /* q > 0.5 */
+        n += 1;
+        carry = 0;
+        for(i = 0; i < jz; i++) { /* compute 1-q */
+            j = iq[i];
+            if(carry == 0) {
+                if(j != 0) {
+                    carry = 1;
+                    iq[i] = 0x1000000 - j;
+                }
+            } else
+                iq[i] = 0xffffff - j;
+        }
+        if(q0 > 0) { /* rare case: chance is 1 in 12 */
+            switch(q0) {
+                case 1: iq[jz - 1] &= 0x7fffff; break;
+                case 2: iq[jz - 1] &= 0x3fffff; break;
+            }
+        }
+        if(ih == 2) {
+            z = one - z;
+            if(carry != 0) z -= dmath_ol_scalbn(one, q0);
+        }
+    }
+
+    /* check if recomputation is needed */
+    if(z == zero) {
+        j = 0;
+        for(i = jz - 1; i >= jk; i--)
+            j |= iq[i];
+        if(j == 0) { /* need recomputation */
+            for(k = 1; iq[jk - k] == 0; k++)
+                ; /* k = no. of terms needed */
+
+            for(i = jz + 1; i <= jz + k; i++) { /* add q[jz+1] to q[jz+k] */
+                f[jx + i] = (double)ipio2[jv + i];
+                for(j = 0, fw = 0.0; j <= jx; j++)
+                    fw += x[j] * f[jx + i - j];
+                q[i] = fw;
+            }
+            jz += k;
+            goto recompute;
+        }
+    }
+
+    /* chop off zero terms */
+    if(z == 0.0) {
+        jz -= 1;
+        q0 -= 24;
+        while(iq[jz] == 0) {
+            jz--;
+            q0 -= 24;
+        }
+    } else { /* break z into 24-bit if necessary */
+        z = dmath_ol_scalbn(z, -q0);
+        if(z >= two24) {
+            fw = (double)((int32_t)(twon24 * z));
+            iq[jz] = (int32_t)(z - two24 * fw);
+            jz += 1;
+            q0 += 24;
+            iq[jz] = (int32_t)fw;
+        } else
+            iq[jz] = (int32_t)z;
+    }
+
+    /* convert integer "bit" chunk to floating-point value */
+    fw = dmath_ol_scalbn(one, q0);
+    for(i = jz; i >= 0; i--) {
+        q[i] = fw * (double)iq[i];
+        fw *= twon24;
+    }
+
+    /* compute PIo2[0,...,jp]*q[jz,...,0] */
+    for(i = jz; i >= 0; i--) {
+        for(fw = 0.0, k = 0; k <= jp && k <= jz - i; k++)
+            fw += PIo2[k] * q[i + k];
+        fq[jz - i] = fw;
+    }
+
+    /* compress fq[] into y[] */
+    fw = 0.0;
+    for(i = jz; i >= 0; i--)
+        fw += fq[i];
+    DMATH_OL_STRICT_ASSIGN(double, fw, fw);
+    y[0] = (ih == 0) ? fw : -fw;
+    fw = fq[0] - fw;
+    for(i = 1; i <= jz; i++)
+        fw += fq[i];
+    y[1] = (ih == 0) ? fw : -fw;
+    return n & 7;
+}
+
+// OpenLibm src/e_rem_pio2.c
+/* @(#)e_rem_pio2.c 1.4 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ * Optimized by Bruce D. Evans.
+ */
+
+/* dmath_ol_rem_pio2(x,y)
+ *
+ * return the remainder of x rem pi/2 in y[0]+y[1]
+ * use dmath_ol_kernel_rem_pio2()
+ */
+
+/*
+ * invpio2:  53 bits of 2/pi
+ * pio2_1:   first  33 bit of pi/2
+ * pio2_1t:  pi/2 - pio2_1
+ * pio2_2:   second 33 bit of pi/2
+ * pio2_2t:  pi/2 - (pio2_1+pio2_2)
+ * pio2_3:   third  33 bit of pi/2
+ * pio2_3t:  pi/2 - (pio2_1+pio2_2+pio2_3)
+ */
+
+static int dmath_ol_rem_pio2(double x, double* y) {
+    static const double zero = 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
+        two24 = 1.67772160000000000000e+07,                /* 0x41700000, 0x00000000 */
+        invpio2 = 6.36619772367581382433e-01,              /* 0x3FE45F30, 0x6DC9C883 */
+        pio2_1 = 1.57079632673412561417e+00,               /* 0x3FF921FB, 0x54400000 */
+        pio2_1t = 6.07710050650619224932e-11,              /* 0x3DD0B461, 0x1A626331 */
+        pio2_2 = 6.07710050630396597660e-11,               /* 0x3DD0B461, 0x1A600000 */
+        pio2_2t = 2.02226624879595063154e-21,              /* 0x3BA3198A, 0x2E037073 */
+        pio2_3 = 2.02226624871116645580e-21,               /* 0x3BA3198A, 0x2E000000 */
+        pio2_3t = 8.47842766036889956997e-32;              /* 0x397B839A, 0x252049C1 */
+
+    double z, w, t, r, fn;
+    double tx[3], ty[2];
+    int32_t e0, i, j, nx, n, ix, hx;
+    uint32_t low;
+
+    DMATH_OL_GET_HIGH_WORD(hx, x); /* high word of x */
+    ix = hx & 0x7fffffff;
+    if(ix <= 0x400f6a7a) {            /* |x| ~<= 5pi/4 */
+        if((ix & 0xfffff) == 0x921fb) /* |x| ~= pi/2 or 2pi/2 */
+            goto medium;              /* cancellation -- use medium case */
+        if(ix <= 0x4002d97c) {        /* |x| ~<= 3pi/4 */
+            if(hx > 0) {
+                z = x - pio2_1; /* one round good to 85 bits */
+                y[0] = z - pio2_1t;
+                y[1] = (z - y[0]) - pio2_1t;
+                return 1;
+            } else {
+                z = x + pio2_1;
+                y[0] = z + pio2_1t;
+                y[1] = (z - y[0]) + pio2_1t;
+                return -1;
+            }
+        } else {
+            if(hx > 0) {
+                z = x - 2 * pio2_1;
+                y[0] = z - 2 * pio2_1t;
+                y[1] = (z - y[0]) - 2 * pio2_1t;
+                return 2;
+            } else {
+                z = x + 2 * pio2_1;
+                y[0] = z + 2 * pio2_1t;
+                y[1] = (z - y[0]) + 2 * pio2_1t;
+                return -2;
+            }
+        }
+    }
+    if(ix <= 0x401c463b) {       /* |x| ~<= 9pi/4 */
+        if(ix <= 0x4015fdbc) {   /* |x| ~<= 7pi/4 */
+            if(ix == 0x4012d97c) /* |x| ~= 3pi/2 */
+                goto medium;
+            if(hx > 0) {
+                z = x - 3 * pio2_1;
+                y[0] = z - 3 * pio2_1t;
+                y[1] = (z - y[0]) - 3 * pio2_1t;
+                return 3;
+            } else {
+                z = x + 3 * pio2_1;
+                y[0] = z + 3 * pio2_1t;
+                y[1] = (z - y[0]) + 3 * pio2_1t;
+                return -3;
+            }
+        } else {
+            if(ix == 0x401921fb) /* |x| ~= 4pi/2 */
+                goto medium;
+            if(hx > 0) {
+                z = x - 4 * pio2_1;
+                y[0] = z - 4 * pio2_1t;
+                y[1] = (z - y[0]) - 4 * pio2_1t;
+                return 4;
+            } else {
+                z = x + 4 * pio2_1;
+                y[0] = z + 4 * pio2_1t;
+                y[1] = (z - y[0]) + 4 * pio2_1t;
+                return -4;
+            }
+        }
+    }
+    if(ix < 0x413921fb) { /* |x| ~< 2^20*(pi/2), medium size */
+    medium:
+        /* Use a specialized rint() to get fn.  Assume round-to-nearest. */
+        DMATH_OL_STRICT_ASSIGN(double, fn, x* invpio2 + 0x1.8p52);
+        fn = fn - 0x1.8p52;
+        n = (int32_t)fn;
+        r = x - fn * pio2_1;
+        w = fn * pio2_1t; /* 1st round good to 85 bit */
+        {
+            uint32_t high;
+            j = ix >> 20;
+            y[0] = r - w;
+            DMATH_OL_GET_HIGH_WORD(high, y[0]);
+            i = j - ((high >> 20) & 0x7ff);
+            if(i > 16) { /* 2nd iteration needed, good to 118 */
+                t = r;
+                w = fn * pio2_2;
+                r = t - w;
+                w = fn * pio2_2t - ((t - r) - w);
+                y[0] = r - w;
+                DMATH_OL_GET_HIGH_WORD(high, y[0]);
+                i = j - ((high >> 20) & 0x7ff);
+                if(i > 49) { /* 3rd iteration need, 151 bits acc */
+                    t = r;   /* will cover all possible cases */
+                    w = fn * pio2_3;
+                    r = t - w;
+                    w = fn * pio2_3t - ((t - r) - w);
+                    y[0] = r - w;
+                }
+            }
+        }
+        y[1] = (r - y[0]) - w;
+        return n;
+    }
+    /*
+     * all other (large) arguments
+     */
+    if(ix >= 0x7ff00000) { /* x is inf or NaN */
+        y[0] = y[1] = x - x;
+        return 0;
+    }
+    /* Normalize |x| to [2^23, 2^24). e0 can be negative, so multiply
+     * instead of left-shifting a signed exponent. */
+    DMATH_OL_GET_LOW_WORD(low, x);
+    e0 = (ix >> 20) - 1046; /* e0 = ilogb(x)-23; */
+    DMATH_OL_INSERT_WORDS(z, ix - (e0 * 0x00100000), low);
+    for(i = 0; i < 2; i++) {
+        tx[i] = (double)((int32_t)(z));
+        z = (z - tx[i]) * two24;
+    }
+    tx[2] = z;
+    nx = 3;
+    while(tx[nx - 1] == zero)
+        nx--; /* skip zero term */
+    n = dmath_ol_kernel_rem_pio2(tx, ty, e0, nx);
+    if(hx < 0) {
+        y[0] = -ty[0];
+        y[1] = -ty[1];
+        return -n;
+    }
+    y[0] = ty[0];
+    y[1] = ty[1];
+    return n;
+}
+
+// OpenLibm src/k_sin.c
+/* @(#)k_sin.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* dmath_ol_kernel_sin( x, y, iy)
+ * kernel sin function on ~[-pi/4, pi/4] (except on -0), pi/4 ~ 0.7854
+ * Input x is assumed to be bounded by ~pi/4 in magnitude.
+ * Input y is the tail of x.
+ * Input iy indicates whether y is 0. (if iy=0, y assume to be 0).
+ *
+ * Algorithm
+ *	1. Since sin(-x) = -sin(x), we need only to consider positive x.
+ *	2. Callers must return sin(-0) = -0 without calling here since our
+ *	   odd polynomial is not evaluated in a way that preserves -0.
+ *	   Callers may do the optimization sin(x) ~ x for tiny x.
+ *	3. sin(x) is approximated by a polynomial of degree 13 on
+ *	   [0,pi/4]
+ *		  	         3            13
+ *	   	sin(x) ~ x + S1*x + ... + S6*x
+ *	   where
+ *
+ * 	|sin(x)         2     4     6     8     10     12  |     -58
+ * 	|----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x  +S6*x   )| <= 2
+ * 	|  x 					           |
+ *
+ *	4. sin(x+y) = sin(x) + sin'(x')*y
+ *		    ~ sin(x) + (1-x*x/2)*y
+ *	   For better accuracy, let
+ *		     3      2      2      2      2
+ *		r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6))))
+ *	   then                   3    2
+ *		sin(x) = x + (S1*x + (x *(r-y/2)+y))
+ */
+
+static double dmath_ol_kernel_sin(double x, double y, int iy) {
+    static const double half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
+        S1 = -1.66666666666666324348e-01,                  /* 0xBFC55555, 0x55555549 */
+        S2 = 8.33333333332248946124e-03,                   /* 0x3F811111, 0x1110F8A6 */
+        S3 = -1.98412698298579493134e-04,                  /* 0xBF2A01A0, 0x19C161D5 */
+        S4 = 2.75573137070700676789e-06,                   /* 0x3EC71DE3, 0x57B1FE7D */
+        S5 = -2.50507602534068634195e-08,                  /* 0xBE5AE5E6, 0x8A2B9CEB */
+        S6 = 1.58969099521155010221e-10;                   /* 0x3DE5D93A, 0x5ACFD57C */
+
+    double z, r, v, w;
+
+    z = x * x;
+    w = z * z;
+    r = S2 + z * (S3 + z * S4) + z * w * (S5 + z * S6);
+    v = z * x;
+    if(iy == 0)
+        return x + v * (S1 + z * r);
+    else
+        return x - ((z * (half * y - v * r) - y) - v * S1);
+}
+
+// OpenLibm src/k_cos.c
+/* @(#)k_cos.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * dmath_ol_kernel_cos( x,  y )
+ * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164
+ * Input x is assumed to be bounded by ~pi/4 in magnitude.
+ * Input y is the tail of x.
+ *
+ * Algorithm
+ *	1. Since cos(-x) = cos(x), we need only to consider positive x.
+ *	2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0.
+ *	3. cos(x) is approximated by a polynomial of degree 14 on
+ *	   [0,pi/4]
+ *		  	                 4            14
+ *	   	cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x
+ *	   where the remez error is
+ *
+ * 	|              2     4     6     8     10    12     14 |     -58
+ * 	|cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x  +C6*x  )| <= 2
+ * 	|    					               |
+ *
+ * 	               4     6     8     10    12     14
+ *	4. let r = C1*x +C2*x +C3*x +C4*x +C5*x  +C6*x  , then
+ *	       cos(x) ~ 1 - x*x/2 + r
+ *	   since cos(x+y) ~ cos(x) - sin(x)*y
+ *			  ~ cos(x) - x*y,
+ *	   a correction term is necessary in cos(x) and hence
+ *		cos(x+y) = 1 - (x*x/2 - (r - x*y))
+ *	   For better accuracy, rearrange to
+ *		cos(x+y) ~ w + (tmp + (r-x*y))
+ *	   where w = 1 - x*x/2 and tmp is a tiny correction term
+ *	   (1 - x*x/2 == w + tmp exactly in infinite precision).
+ *	   The exactness of w + tmp in infinite precision depends on w
+ *	   and tmp having the same precision as x.  If they have extra
+ *	   precision due to compiler bugs, then the extra precision is
+ *	   only good provided it is retained in all terms of the final
+ *	   expression for cos().  Retention happens in all cases tested
+ *	   under FreeBSD, so don't pessimize things by forcibly clipping
+ *	   any extra precision in w.
+ */
+
+static double dmath_ol_kernel_cos(double x, double y) {
+    static const double one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+        C1 = 4.16666666666666019037e-02,                  /* 0x3FA55555, 0x5555554C */
+        C2 = -1.38888888888741095749e-03,                 /* 0xBF56C16C, 0x16C15177 */
+        C3 = 2.48015872894767294178e-05,                  /* 0x3EFA01A0, 0x19CB1590 */
+        C4 = -2.75573143513906633035e-07,                 /* 0xBE927E4F, 0x809C52AD */
+        C5 = 2.08757232129817482790e-09,                  /* 0x3E21EE9E, 0xBDB4B1C4 */
+        C6 = -1.13596475577881948265e-11;                 /* 0xBDA8FAE9, 0xBE8838D4 */
+
+    double hz, z, r, w;
+
+    z = x * x;
+    w = z * z;
+    r = z * (C1 + z * (C2 + z * C3)) + w * w * (C4 + z * (C5 + z * C6));
+    hz = 0.5 * z;
+    w = one - hz;
+    return w + (((one - w) - hz) + (z * r - x * y));
+}
+
+// OpenLibm src/k_tan.c
+/* @(#)k_tan.c 1.5 04/04/22 SMI */
+
+/*
+ * ====================================================
+ * Copyright 2004 Sun Microsystems, Inc.  All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* INDENT OFF */
+
+/* dmath_ol_kernel_tan( x, y, k )
+ * kernel tan function on ~[-pi/4, pi/4] (except on -0), pi/4 ~ 0.7854
+ * Input x is assumed to be bounded by ~pi/4 in magnitude.
+ * Input y is the tail of x.
+ * Input k indicates whether tan (if k = 1) or -1/tan (if k = -1) is returned.
+ *
+ * Algorithm
+ *	1. Since tan(-x) = -tan(x), we need only to consider positive x.
+ *	2. Callers must return tan(-0) = -0 without calling here since our
+ *	   odd polynomial is not evaluated in a way that preserves -0.
+ *	   Callers may do the optimization tan(x) ~ x for tiny x.
+ *	3. tan(x) is approximated by a odd polynomial of degree 27 on
+ *	   [0,0.67434]
+ *		  	         3             27
+ *	   	tan(x) ~ x + T1*x + ... + T13*x
+ *	   where
+ *
+ * 	        |tan(x)         2     4            26   |     -59.2
+ * 	        |----- - (1+T1*x +T2*x +.... +T13*x    )| <= 2
+ * 	        |  x 					|
+ *
+ *	   Note: tan(x+y) = tan(x) + tan'(x)*y
+ *		          ~ tan(x) + (1+x*x)*y
+ *	   Therefore, for better accuracy in computing tan(x+y), let
+ *		     3      2      2       2       2
+ *		r = x *(T2+x *(T3+x *(...+x *(T12+x *T13))))
+ *	   then
+ *		 		    3    2
+ *		tan(x+y) = x + (T1*x + (x *(r+y)+y))
+ *
+ *      4. For x in [0.67434,pi/4],  let y = pi/4 - x, then
+ *		tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y))
+ *		       = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y)))
+ */
+
+static double dmath_ol_kernel_tan(double x, double y, int iy) {
+    static const double xxx[] = {
+        3.33333333333334091986e-01,               /* 3FD55555, 55555563 */
+        1.33333333333201242699e-01,               /* 3FC11111, 1110FE7A */
+        5.39682539762260521377e-02,               /* 3FABA1BA, 1BB341FE */
+        2.18694882948595424599e-02,               /* 3F9664F4, 8406D637 */
+        8.86323982359930005737e-03,               /* 3F8226E3, E96E8493 */
+        3.59207910759131235356e-03,               /* 3F6D6D22, C9560328 */
+        1.45620945432529025516e-03,               /* 3F57DBC8, FEE08315 */
+        5.88041240820264096874e-04,               /* 3F4344D8, F2F26501 */
+        2.46463134818469906812e-04,               /* 3F3026F7, 1A8D1068 */
+        7.81794442939557092300e-05,               /* 3F147E88, A03792A6 */
+        7.14072491382608190305e-05,               /* 3F12B80F, 32F0A7E9 */
+        -1.85586374855275456654e-05,              /* BEF375CB, DB605373 */
+        2.59073051863633712884e-05,               /* 3EFB2A70, 74BF7AD4 */
+        /* one */ 1.00000000000000000000e+00,     /* 3FF00000, 00000000 */
+        /* xxx[14] */ 7.85398163397448278999e-01, /* 3FE921FB, 54442D18 */
+        /* xxx[15] */ 3.06161699786838301793e-17  /* 3C81A626, 33145C07 */
+    };
+    /* INDENT ON */
+
+    double z, r, v, w, s;
+    int32_t ix, hx;
+
+    DMATH_OL_GET_HIGH_WORD(hx, x);
+    ix = hx & 0x7fffffff;  /* high word of |x| */
+    if(ix >= 0x3FE59428) { /* |x| >= 0.6744 */
+        if(hx < 0) {
+            x = -x;
+            y = -y;
+        }
+        z = xxx[14] - x;
+        w = xxx[15] - y;
+        x = z + w;
+        y = 0.0;
+    }
+    z = x * x;
+    w = z * z;
+    /*
+     * Break x^5*(xxx[1]+x^2*xxx[2]+...) into
+     * x^5(xxx[1]+x^4*xxx[3]+...+x^20*xxx[11]) +
+     * x^5(x^2*(xxx[2]+x^4*xxx[4]+...+x^22*[T12]))
+     */
+    r = xxx[1] + w * (xxx[3] + w * (xxx[5] + w * (xxx[7] + w * (xxx[9] + w * xxx[11]))));
+    v = z * (xxx[2] + w * (xxx[4] + w * (xxx[6] + w * (xxx[8] + w * (xxx[10] + w * xxx[12])))));
+    s = z * x;
+    r = y + z * (s * (r + v) + y);
+    r += xxx[0] * s;
+    w = x + r;
+    if(ix >= 0x3FE59428) {
+        v = (double)iy;
+        return (hx < 0 ? -1.0 : 1.0) * (v - 2.0 * (x - (w * w / (w + v) - r)));
+    }
+    if(iy == 1)
+        return w;
+    else {
+        /*
+         * if allow error up to 2 ulp, simply return
+         * -1.0 / (x+r) here
+         */
+        /* compute -1.0 / (x+r) accurately */
+        double a, t;
+        z = w;
+        DMATH_OL_SET_LOW_WORD(z, 0);
+        v = r - (z - x);  /* z+v = r+x */
+        t = a = -1.0 / w; /* a = -1.0/w */
+        DMATH_OL_SET_LOW_WORD(t, 0);
+        s = 1.0 + t * z;
+        return t + a * (s + t * v);
+    }
+}
+
+// OpenLibm src/s_sin.c
+/* @(#)s_sin.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* dmath_ol_sin(x)
+ * Return sine function of x.
+ *
+ * kernel function:
+ *	dmath_ol_kernel_sin		... sine function on [-pi/4,pi/4]
+ *	dmath_ol_kernel_cos		... cose function on [-pi/4,pi/4]
+ *	dmath_ol_rem_pio2	... argument reduction routine
+ *
+ * Method.
+ *      Let S,C and T denote the dmath_ol_sin, cos and tan respectively on
+ *	[-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
+ *	in [-pi/4 , +pi/4], and let n = k mod 4.
+ *	We have
+ *
+ *          n        dmath_ol_sin(x)      cos(x)        tan(x)
+ *     ----------------------------------------------------------
+ *	    0	       S	   C		 T
+ *	    1	       C	  -S		-1/T
+ *	    2	      -S	  -C		 T
+ *	    3	      -C	   S		-1/T
+ *     ----------------------------------------------------------
+ *
+ * Special cases:
+ *      Let trig be any of dmath_ol_sin, cos, or tan.
+ *      trig(+-INF)  is NaN, with signals;
+ *      trig(NaN)    is that NaN;
+ *
+ * Accuracy:
+ *	TRIG(x) returns trig(x) nearly rounded
+ */
+
+static double dmath_ol_sin(double x) {
+
+    double y[2], z = 0.0;
+    int32_t n, ix;
+
+    /* High word of x. */
+    DMATH_OL_GET_HIGH_WORD(ix, x);
+
+    /* |x| ~< pi/4 */
+    ix &= 0x7fffffff;
+    if(ix <= 0x3fe921fb) {
+        if(ix < 0x3e500000) /* |x| < 2**-26 */
+        {
+            if((int)x == 0) return x;
+        } /* generate inexact */
+        return dmath_ol_kernel_sin(x, z, 0);
+    }
+
+    /* dmath_ol_sin(Inf or NaN) is NaN */
+    else if(ix >= 0x7ff00000)
+        return x - x;
+
+    /* argument reduction needed */
+    else {
+        n = dmath_ol_rem_pio2(x, y);
+        switch(n & 3) {
+            case 0: return dmath_ol_kernel_sin(y[0], y[1], 1);
+            case 1: return dmath_ol_kernel_cos(y[0], y[1]);
+            case 2: return -dmath_ol_kernel_sin(y[0], y[1], 1);
+            default: return -dmath_ol_kernel_cos(y[0], y[1]);
+        }
+    }
+}
+
+// OpenLibm src/s_cos.c
+/* @(#)s_cos.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* dmath_ol_cos(x)
+ * Return cosine function of x.
+ *
+ * kernel function:
+ *	dmath_ol_kernel_sin		... sine function on [-pi/4,pi/4]
+ *	dmath_ol_kernel_cos		... cosine function on [-pi/4,pi/4]
+ *	dmath_ol_rem_pio2	... argument reduction routine
+ *
+ * Method.
+ *      Let S,C and T denote the sin, dmath_ol_cos and tan respectively on
+ *	[-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
+ *	in [-pi/4 , +pi/4], and let n = k mod 4.
+ *	We have
+ *
+ *          n        sin(x)      dmath_ol_cos(x)        tan(x)
+ *     ----------------------------------------------------------
+ *	    0	       S	   C		 T
+ *	    1	       C	  -S		-1/T
+ *	    2	      -S	  -C		 T
+ *	    3	      -C	   S		-1/T
+ *     ----------------------------------------------------------
+ *
+ * Special cases:
+ *      Let trig be any of sin, dmath_ol_cos, or tan.
+ *      trig(+-INF)  is NaN, with signals;
+ *      trig(NaN)    is that NaN;
+ *
+ * Accuracy:
+ *	TRIG(x) returns trig(x) nearly rounded
+ */
+
+static double dmath_ol_cos(double x) {
+
+    double y[2], z = 0.0;
+    int32_t n, ix;
+
+    /* High word of x. */
+    DMATH_OL_GET_HIGH_WORD(ix, x);
+
+    /* |x| ~< pi/4 */
+    ix &= 0x7fffffff;
+    if(ix <= 0x3fe921fb) {
+        if(ix < 0x3e46a09e)               /* if x < 2**-27 * sqrt(2) */
+            if(((int)x) == 0) return 1.0; /* generate inexact */
+        return dmath_ol_kernel_cos(x, z);
+    }
+
+    /* dmath_ol_cos(Inf or NaN) is NaN */
+    else if(ix >= 0x7ff00000)
+        return x - x;
+
+    /* argument reduction needed */
+    else {
+        n = dmath_ol_rem_pio2(x, y);
+        switch(n & 3) {
+            case 0: return dmath_ol_kernel_cos(y[0], y[1]);
+            case 1: return -dmath_ol_kernel_sin(y[0], y[1], 1);
+            case 2: return -dmath_ol_kernel_cos(y[0], y[1]);
+            default: return dmath_ol_kernel_sin(y[0], y[1], 1);
+        }
+    }
+}
+
+// OpenLibm src/s_tan.c
+/* @(#)s_tan.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* dmath_ol_tan(x)
+ * Return tangent function of x.
+ *
+ * kernel function:
+ *	dmath_ol_kernel_tan		... tangent function on [-pi/4,pi/4]
+ *	dmath_ol_rem_pio2	... argument reduction routine
+ *
+ * Method.
+ *      Let S,C and T denote the sin, cos and dmath_ol_tan respectively on
+ *	[-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
+ *	in [-pi/4 , +pi/4], and let n = k mod 4.
+ *	We have
+ *
+ *          n        sin(x)      cos(x)        dmath_ol_tan(x)
+ *     ----------------------------------------------------------
+ *	    0	       S	   C		 T
+ *	    1	       C	  -S		-1/T
+ *	    2	      -S	  -C		 T
+ *	    3	      -C	   S		-1/T
+ *     ----------------------------------------------------------
+ *
+ * Special cases:
+ *      Let trig be any of sin, cos, or dmath_ol_tan.
+ *      trig(+-INF)  is NaN, with signals;
+ *      trig(NaN)    is that NaN;
+ *
+ * Accuracy:
+ *	TRIG(x) returns trig(x) nearly rounded
+ */
+
+static double dmath_ol_tan(double x) {
+
+    double y[2], z = 0.0;
+    int32_t n, ix;
+
+    /* High word of x. */
+    DMATH_OL_GET_HIGH_WORD(ix, x);
+
+    /* |x| ~< pi/4 */
+    ix &= 0x7fffffff;
+    if(ix <= 0x3fe921fb) {
+        if(ix < 0x3e400000)           /* x < 2**-27 */
+            if((int)x == 0) return x; /* generate inexact */
+        return dmath_ol_kernel_tan(x, z, 1);
+    }
+
+    /* dmath_ol_tan(Inf or NaN) is NaN */
+    else if(ix >= 0x7ff00000)
+        return x - x; /* NaN */
+
+    /* argument reduction needed */
+    else {
+        n = dmath_ol_rem_pio2(x, y);
+        return dmath_ol_kernel_tan(y[0], y[1], 1 - ((n & 1) << 1)); /*   1 -- n even
+                                                            -1 -- n odd */
+    }
+}
+
+double dmath_sin(double x) { return dmath_ol_result(dmath_ol_sin(x)); }
+
+double dmath_cos(double x) { return dmath_ol_result(dmath_ol_cos(x)); }
+
+double dmath_tan(double x) { return dmath_ol_result(dmath_ol_tan(x)); }
+
+// OpenLibm src/s_sincos.c (reuse the separate kernels and their tiny-input cutoffs)
+/* @(#)s_sincos.c 5.1 13/07/15 */
+/* See openlibm LICENSE.md for full license details.
+ *
+ * ====================================================
+ * This file is derived from fdlibm:
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ *
+ * ====================================================
+ * Copyright (C) 2013 Elliot Saba. All rights reserved.
+ *
+ * Developed at the University of Washington.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+void dmath_sincos(double x, double* sin, double* cos) {
+    uint32_t ix = (uint32_t)(dmath_ol_bits(x) >> 32) & 0x7fffffff;
+    if(ix <= 0x3fe921fb) {
+        *sin = ix < 0x3e500000 ? x : dmath_ol_kernel_sin(x, 0.0, 0);
+        *cos = ix < 0x3e46a09e ? 1.0 : dmath_ol_kernel_cos(x, 0.0);
+        return;
+    }
+    if(ix >= 0x7ff00000) {
+        *sin = *cos = dmath_ol_result(x - x);
+        return;
+    }
+    double y[2];
+    int n = dmath_ol_rem_pio2(x, y);
+    double s = dmath_ol_kernel_sin(y[0], y[1], 1);
+    double c = dmath_ol_kernel_cos(y[0], y[1]);
+    switch((unsigned)n & 3) {
+        case 0:
+            *sin = s;
+            *cos = c;
+            break;
+        case 1:
+            *sin = c;
+            *cos = -s;
+            break;
+        case 2:
+            *sin = -s;
+            *cos = -c;
+            break;
+        default:
+            *sin = -c;
+            *cos = s;
+            break;
+    }
+}
+
+double dmath_exp(double x) { return dmath_ol_result(dmath_ol_exp(x)); }
+
+double dmath_exp2(double x) { return dmath_ol_result(dmath_ol_exp2(x)); }
+
+double dmath_log(double x) { return dmath_ol_result(dmath_ol_log(x)); }
+
+double dmath_log2(double x) { return dmath_ol_result(dmath_ol_log2(x)); }
+
+double dmath_log10(double x) { return dmath_ol_result(dmath_ol_log10(x)); }
+
+double dmath_pow(double x, double y) { return dmath_ol_result(dmath_ol_pow(x, y)); }
+
+double dmath_exp10(double x) { return dmath_pow(10.0, x); }
+
+double dmath_log_base(double x, double base) {
+    return dmath_ol_result(dmath_ol_log(x) / dmath_ol_log(base));
+}
+
+#undef DMATH_OL_GET_HIGH_WORD
+#undef DMATH_OL_GET_LOW_WORD
+#undef DMATH_OL_EXTRACT_WORDS
+#undef DMATH_OL_INSERT_WORDS
+#undef DMATH_OL_SET_HIGH_WORD
+#undef DMATH_OL_SET_LOW_WORD
+#undef DMATH_OL_STRICT_ASSIGN
+

+ 3 - 3
src/common/dmath_zig.c

@@ -2,9 +2,9 @@
 // them from musl (MIT licensed):
 // them from musl (MIT licensed):
 // https://github.com/ziglang/zig/blob/master/lib/std/math/
 // https://github.com/ziglang/zig/blob/master/lib/std/math/
 //
 //
-// These live in their own file so the provenance stays obvious: each function
-// below is a line-by-line translation of the Zig source linked above it, and
-// should be re-synced from there rather than hand-tuned.
+// The finite evaluation order is retained from the original translation.
+// The historical upstream links do not pin a revision. Numerical changes need
+// review and independent accuracy/determinism checks, not an automatic sync.
 
 
 #include "pocketpy/common/dmath.h"
 #include "pocketpy/common/dmath.h"
 #include <stdint.h>
 #include <stdint.h>

+ 22 - 15
src/modules/math.c

@@ -11,12 +11,21 @@
         return true;                                                                               \
         return true;                                                                               \
     }
     }
 
 
-#define ONE_ARG_INT_FUNC(name, func)                                                               \
+#define ONE_ARG_ROUND_FUNC(name, func)                                                             \
     static bool math_##name(int argc, py_Ref argv) {                                               \
     static bool math_##name(int argc, py_Ref argv) {                                               \
         PY_CHECK_ARGC(1);                                                                          \
         PY_CHECK_ARGC(1);                                                                          \
+        if(py_isint(py_arg(0))) {                                                                  \
+            py_newint(py_retval(), py_toint(py_arg(0)));                                           \
+            return true;                                                                          \
+        }                                                                                         \
         double x;                                                                                  \
         double x;                                                                                  \
         if(!py_castfloat(py_arg(0), &x)) return false;                                             \
         if(!py_castfloat(py_arg(0), &x)) return false;                                             \
-        py_newint(py_retval(), (py_i64)func(x));                                                   \
+        double rounded = func(x);                                                                 \
+        /* Keep integer results when representable; never cast NaN/Inf or an out-of-range value. */ \
+        if(rounded >= -0x1p63 && rounded < 0x1p63)                                                 \
+            py_newint(py_retval(), (py_i64)rounded);                                               \
+        else                                                                                      \
+            py_newfloat(py_retval(), rounded);                                                    \
         return true;                                                                               \
         return true;                                                                               \
     }
     }
 
 
@@ -39,9 +48,9 @@
         return true;                                                                               \
         return true;                                                                               \
     }
     }
 
 
-ONE_ARG_INT_FUNC(ceil, dmath_ceil)
-ONE_ARG_INT_FUNC(floor, dmath_floor)
-ONE_ARG_INT_FUNC(trunc, dmath_trunc)
+ONE_ARG_ROUND_FUNC(ceil, dmath_ceil)
+ONE_ARG_ROUND_FUNC(floor, dmath_floor)
+ONE_ARG_ROUND_FUNC(trunc, dmath_trunc)
 ONE_ARG_FUNC(fabs, dmath_fabs)
 ONE_ARG_FUNC(fabs, dmath_fabs)
 
 
 static bool math_fsum(int argc, py_Ref argv) {
 static bool math_fsum(int argc, py_Ref argv) {
@@ -93,23 +102,19 @@ static bool math_isclose(int argc, py_Ref argv) {
     return true;
     return true;
 }
 }
 
 
+// Overflow deliberately returns signed infinity instead of raising an exception.
 ONE_ARG_FUNC(exp, dmath_exp)
 ONE_ARG_FUNC(exp, dmath_exp)
 
 
 static bool math_log(int argc, py_Ref argv) {
 static bool math_log(int argc, py_Ref argv) {
+    if(argc != 1 && argc != 2) return TypeError("log() takes 1 or 2 arguments");
     double x;
     double x;
     if(!py_castfloat(py_arg(0), &x)) return false;
     if(!py_castfloat(py_arg(0), &x)) return false;
-    if(x < 0) {
-        py_newfloat(py_retval(), DMATH_NAN);
-        return true;
-    }
     if(argc == 1) {
     if(argc == 1) {
         py_newfloat(py_retval(), dmath_log(x));
         py_newfloat(py_retval(), dmath_log(x));
-    } else if(argc == 2) {
+    } else {
         double base;
         double base;
         if(!py_castfloat(py_arg(1), &base)) return false;
         if(!py_castfloat(py_arg(1), &base)) return false;
-        py_newfloat(py_retval(), dmath_log2(x) / dmath_log2(base));
-    } else {
-        return TypeError("log() takes 1 or 2 arguments");
+        py_newfloat(py_retval(), dmath_log_base(x, base));
     }
     }
     return true;
     return true;
 }
 }
@@ -151,8 +156,10 @@ TWO_ARG_FUNC(fmod, dmath_fmod)
 
 
 static bool math_modf(int argc, py_Ref argv) {
 static bool math_modf(int argc, py_Ref argv) {
     PY_CHECK_ARGC(1);
     PY_CHECK_ARGC(1);
+    double x;
+    if(!py_castfloat(py_arg(0), &x)) return false;
     double i;
     double i;
-    double f = dmath_modf(py_tofloat(py_arg(0)), &i);
+    double f = dmath_modf(x, &i);
     py_Ref p = py_newtuple(py_retval(), 2);
     py_Ref p = py_newtuple(py_retval(), 2);
     py_newfloat(&p[0], f);
     py_newfloat(&p[0], f);
     py_newfloat(&p[1], i);
     py_newfloat(&p[1], i);
@@ -222,5 +229,5 @@ void pk__add_module_math() {
 
 
 #undef ONE_ARG_FUNC
 #undef ONE_ARG_FUNC
 #undef ONE_ARG_BOOL_FUNC
 #undef ONE_ARG_BOOL_FUNC
-#undef ONE_ARG_INT_FUNC
+#undef ONE_ARG_ROUND_FUNC
 #undef TWO_ARG_FUNC
 #undef TWO_ARG_FUNC

+ 436 - 0
src2/test_dmath.c

@@ -0,0 +1,436 @@
+/* Per-function binary64 tests; see tests/dmath/README.md. No host-libm oracle. */
+#include "pocketpy/common/dmath.h"
+#include <fenv.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef enum {
+    T_isfinite,
+    T_isinf,
+    T_isnan,
+    T_isnormal,
+    T_fabs,
+    T_copysign,
+    T_fmin,
+    T_fmax,
+    T_ceil,
+    T_floor,
+    T_trunc,
+    T_modf,
+    T_fmod,
+    T_sqrt,
+    T_cbrt,
+    T_exp,
+    T_exp2,
+    T_exp10,
+    T_pow,
+    T_log,
+    T_log2,
+    T_log10,
+    T_log_base,
+    T_sin,
+    T_cos,
+    T_tan,
+    T_sincos,
+    T_asin,
+    T_acos,
+    T_atan,
+    T_atan2
+} Operation;
+
+typedef struct {
+    const char* category;
+    const char* name;
+    Operation op;
+    int outputs;
+    int rounding_independent;
+} Function;
+
+const static Function functions[] = {
+    {"classification",         "isfinite", T_isfinite, 1, 1},
+    {"classification",         "isinf",    T_isinf,    1, 1},
+    {"classification",         "isnan",    T_isnan,    1, 1},
+    {"classification",         "isnormal", T_isnormal, 1, 1},
+    {"sign_and_order",         "fabs",     T_fabs,     1, 1},
+    {"sign_and_order",         "copysign", T_copysign, 1, 1},
+    {"sign_and_order",         "fmin",     T_fmin,     1, 1},
+    {"sign_and_order",         "fmax",     T_fmax,     1, 1},
+    {"rounding_and_remainder", "ceil",     T_ceil,     1, 1},
+    {"rounding_and_remainder", "floor",    T_floor,    1, 1},
+    {"rounding_and_remainder", "trunc",    T_trunc,    1, 1},
+    {"rounding_and_remainder", "modf",     T_modf,     2, 1},
+    {"rounding_and_remainder", "fmod",     T_fmod,     1, 1},
+    {"roots",                  "sqrt",     T_sqrt,     1, 0},
+    {"roots",                  "cbrt",     T_cbrt,     1, 0},
+    {"exponentials",           "exp",      T_exp,      1, 0},
+    {"exponentials",           "exp2",     T_exp2,     1, 0},
+    {"exponentials",           "exp10",    T_exp10,    1, 0},
+    {"exponentials",           "pow",      T_pow,      1, 0},
+    {"logarithms",             "log",      T_log,      1, 0},
+    {"logarithms",             "log2",     T_log2,     1, 0},
+    {"logarithms",             "log10",    T_log10,    1, 0},
+    {"logarithms",             "log_base", T_log_base, 1, 0},
+    {"trigonometry",           "sin",      T_sin,      1, 0},
+    {"trigonometry",           "cos",      T_cos,      1, 0},
+    {"trigonometry",           "tan",      T_tan,      1, 0},
+    {"trigonometry",           "sincos",   T_sincos,   2, 0},
+    {"inverse_trigonometry",   "asin",     T_asin,     1, 0},
+    {"inverse_trigonometry",   "acos",     T_acos,     1, 0},
+    {"inverse_trigonometry",   "atan",     T_atan,     1, 0},
+    {"inverse_trigonometry",   "atan2",    T_atan2,    1, 0},
+};
+
+const static uint64_t magnitude_mask = UINT64_C(0x7fffffffffffffff);
+const static uint64_t infinity_bits = UINT64_C(0x7ff0000000000000);
+const static uint64_t canonical_nan = UINT64_C(0x7ff8000000000000);
+const static uint64_t sign_bit = UINT64_C(0x8000000000000000);
+static int failures;
+
+static void evaluate(const Function* f, uint64_t a, uint64_t b, uint64_t out[2]) {
+    double x = pk_dmath_from_bits(a), y = pk_dmath_from_bits(b), z = 0, aux = 0;
+    out[1] = 0;
+    switch(f->op) {
+        case T_isfinite: out[0] = dmath_isfinite(x); return;
+        case T_isinf: out[0] = dmath_isinf(x); return;
+        case T_isnan: out[0] = dmath_isnan(x); return;
+        case T_isnormal: out[0] = dmath_isnormal(x); return;
+        case T_fabs: z = dmath_fabs(x); break;
+        case T_copysign: z = dmath_copysign(x, y); break;
+        case T_fmin: z = dmath_fmin(x, y); break;
+        case T_fmax: z = dmath_fmax(x, y); break;
+        case T_ceil: z = dmath_ceil(x); break;
+        case T_floor: z = dmath_floor(x); break;
+        case T_trunc: z = dmath_trunc(x); break;
+        case T_modf: z = dmath_modf(x, &aux); break;
+        case T_fmod: z = dmath_fmod(x, y); break;
+        case T_sqrt: z = dmath_sqrt(x); break;
+        case T_cbrt: z = dmath_cbrt(x); break;
+        case T_exp: z = dmath_exp(x); break;
+        case T_exp2: z = dmath_exp2(x); break;
+        case T_exp10: z = dmath_exp10(x); break;
+        case T_pow: z = dmath_pow(x, y); break;
+        case T_log: z = dmath_log(x); break;
+        case T_log2: z = dmath_log2(x); break;
+        case T_log10: z = dmath_log10(x); break;
+        case T_log_base: z = dmath_log_base(x, y); break;
+        case T_sin: z = dmath_sin(x); break;
+        case T_cos: z = dmath_cos(x); break;
+        case T_tan: z = dmath_tan(x); break;
+        case T_sincos: dmath_sincos(x, &z, &aux); break;
+        case T_asin: z = dmath_asin(x); break;
+        case T_acos: z = dmath_acos(x); break;
+        case T_atan: z = dmath_atan(x); break;
+        case T_atan2: z = dmath_atan2(x, y); break;
+    }
+    out[0] = pk_dmath_bits(z);
+    out[1] = pk_dmath_bits(aux);
+}
+
+static void mismatch(const Function* f,
+                     const char* label,
+                     const char* check,
+                     uint64_t a,
+                     uint64_t b,
+                     uint64_t actual,
+                     uint64_t expected) {
+    if(failures++ < 30)
+        fprintf(stderr,
+                "FAIL dmath_%s/%s [%s] x=%016" PRIx64 " y=%016" PRIx64 " got=%016" PRIx64
+                " expected=%016" PRIx64 "\n",
+                f->name,
+                label,
+                check,
+                a,
+                b,
+                actual,
+                expected);
+}
+
+static int accurate(uint64_t actual, uint64_t reference, unsigned ulps) {
+    if(actual == reference) return 1;
+    uint64_t a = actual & magnitude_mask, r = reference & magnitude_mask;
+    // Nonfinite outputs have semantic checks, never NaN payload/sign checks.
+    if(r > infinity_bits) return a > infinity_bits;
+    if(r == infinity_bits) return a == infinity_bits && !((actual ^ reference) & sign_bit);
+    if(r == 0 || a >= infinity_bits || ((actual ^ reference) & sign_bit)) return 0;
+    return (a > r ? a - r : r - a) <= ulps;
+}
+
+static uint64_t signature_word(uint64_t u) {
+    // A fingerprint records NaN classification, not its representation.
+    return (u & magnitude_mask) > infinity_bits ? canonical_nan : u;
+}
+
+static uint64_t parse_word(const char* text) {
+    char* end;
+    uint64_t u = strtoull(text, &end, 16);
+    if(strlen(text) != 16 || *end) {
+        fprintf(stderr, "Invalid binary64 word: %s\n", text);
+        exit(1);
+    }
+    return u;
+}
+
+static uint64_t parse_result(const char* text) {
+    if(strcmp(text, "nan") == 0) return canonical_nan;
+    if(strcmp(text, "+inf") == 0) return infinity_bits;
+    if(strcmp(text, "-inf") == 0) return infinity_bits | sign_bit;
+    return parse_word(text);
+}
+
+static unsigned
+    named_cases(const Function* f, const char* directory, int probe, uint64_t* expected_sweep) {
+    char path[1024], line[1024];
+    snprintf(path, sizeof(path), "%s/%s.txt", directory, f->name);
+    FILE* file = fopen(path, "r");
+    if(!file) {
+        perror(path);
+        exit(1);
+    }
+    unsigned count = 0;
+    int found_sweep = 0;
+    while(fgets(line, sizeof(line), file)) {
+        char fingerprint[32];
+        if(sscanf(line, "# sweep %31s", fingerprint) == 1) {
+            found_sweep = 1;
+            if(strcmp(fingerprint, "PENDING") == 0) {
+                if(!probe) {
+                    fprintf(stderr, "%s: unreviewed sweep\n", path);
+                    failures++;
+                }
+            } else
+                *expected_sweep = parse_word(fingerprint);
+            continue;
+        }
+        if(line[0] == '#' || line[0] == '\n' || line[0] == '\r') continue;
+        char label[128], words[6][32];
+        unsigned ulps;
+        if(sscanf(line,
+                  "%127s %31s %31s %31s %31s %31s %31s %u",
+                  label,
+                  words[0],
+                  words[1],
+                  words[2],
+                  words[3],
+                  words[4],
+                  words[5],
+                  &ulps) != 8) {
+            fprintf(stderr, "Malformed case in %s\n", path);
+            exit(1);
+        }
+        uint64_t a = parse_word(words[0]), b = parse_word(words[1]), out[2];
+        evaluate(f, a, b, out);
+        for(int i = 0; i < f->outputs; i++) {
+            uint64_t ref = parse_result(words[4 + i]);
+            if(!accurate(out[i], ref, ulps))
+                mismatch(f, label, i ? "accuracy/output1" : "accuracy/output0", a, b, out[i], ref);
+            if(!probe) {
+                if(strcmp(words[2 + i], "PENDING") == 0) {
+                    fprintf(stderr, "%s/%s: unreviewed result\n", f->name, label);
+                    failures++;
+                } else {
+                    uint64_t want = parse_result(words[2 + i]);
+                    if(!accurate(out[i], want, 0))
+                        mismatch(f, label, i ? "bits/output1" : "bits/output0", a, b, out[i], want);
+                }
+            }
+        }
+        if(probe == 1)
+            printf("CASE %s %s %016" PRIx64 " %016" PRIx64 "\n",
+                   f->name,
+                   label,
+                   signature_word(out[0]),
+                   signature_word(out[1]));
+        count++;
+    }
+    if(ferror(file) || !count || !found_sweep) {
+        fprintf(stderr, "Incomplete corpus: %s\n", path);
+        exit(1);
+    }
+    fclose(file);
+    return count;
+}
+
+static uint64_t hash_word(uint64_t hash, uint64_t word) {
+    for(int byte = 0; byte < 8; byte++, word >>= 8)
+        hash = (hash ^ (word & 255)) * UINT64_C(1099511628211);
+    return hash;
+}
+
+static uint64_t random_word(uint64_t* state) {
+    // SplitMix64, with unsigned wrapping arithmetic and a new seed per function.
+    uint64_t z = (*state += UINT64_C(0x9e3779b97f4a7c15));
+    z = (z ^ (z >> 30)) * UINT64_C(0xbf58476d1ce4e5b9);
+    z = (z ^ (z >> 27)) * UINT64_C(0x94d049bb133111eb);
+    return z ^ (z >> 31);
+}
+
+static void invariants(const Function* f, uint64_t a, uint64_t b, const uint64_t out[2]) {
+    uint64_t ax = a & magnitude_mask, ay = b & magnitude_mask, expected;
+    int has_exact = 1;
+    switch(f->op) {
+        case T_isfinite: expected = ax < infinity_bits; break;
+        case T_isinf: expected = ax == infinity_bits; break;
+        case T_isnan: expected = ax > infinity_bits; break;
+        case T_isnormal: expected = ax >= UINT64_C(0x0010000000000000) && ax < infinity_bits; break;
+        case T_fabs: expected = ax; break;
+        case T_copysign: expected = ax | (b & sign_bit); break;
+        default:
+            has_exact = 0;
+            expected = 0;
+            break;
+    }
+    if(has_exact) {
+        if(!accurate(out[0], expected, 0))
+            mismatch(f, "sweep", "finite bits/nonfinite class", a, b, out[0], expected);
+        return;
+    }
+    if(f->op == T_fmin || f->op == T_fmax) {
+        uint64_t reverse[2];
+        evaluate(f, b, a, reverse);
+        if(!accurate(out[0], reverse[0], 0))
+            mismatch(f, "sweep", "commutativity", a, b, out[0], reverse[0]);
+    }
+    if(f->op == T_sincos) {
+        expected = pk_dmath_bits(dmath_sin(pk_dmath_from_bits(a)));
+        if(!accurate(out[0], expected, 0))
+            mismatch(f, "sweep", "separate sine", a, b, out[0], expected);
+        expected = pk_dmath_bits(dmath_cos(pk_dmath_from_bits(a)));
+        if(!accurate(out[1], expected, 0))
+            mismatch(f, "sweep", "separate cosine", a, b, out[1], expected);
+    }
+    if(f->op == T_fmod && ax < infinity_bits && ay != 0 && ay <= infinity_bits) {
+        if((out[0] & magnitude_mask) >= ay || ((a ^ out[0]) & sign_bit))
+            mismatch(f, "sweep", "remainder range/sign", a, b, out[0], a & sign_bit);
+    }
+    if(f->op == T_modf && ax < infinity_bits) {
+        double fraction = pk_dmath_from_bits(out[0]), integral = pk_dmath_from_bits(out[1]);
+        expected = pk_dmath_bits(fraction + integral);
+        if(expected != a) mismatch(f, "sweep", "recomposition", a, b, expected, a);
+        if((out[0] & magnitude_mask) >= UINT64_C(0x3ff0000000000000) || ((out[0] ^ a) & sign_bit) ||
+           ((out[1] ^ a) & sign_bit))
+            mismatch(f, "sweep", "fraction range/sign", a, b, out[0], a & sign_bit);
+    }
+}
+
+static uint64_t sweep(const Function* f) {
+    uint64_t state = UINT64_C(0x243f6a8885a308d3);
+    for(const char* p = f->name; *p; p++)
+        state = hash_word(state, (unsigned char)*p);
+    uint64_t hash = UINT64_C(14695981039346656037);
+    // All exponent fields, with fresh significands of both signs, followed by
+    // 16,384 full-range words and an additional stream in useful finite domains.
+    for(unsigned i = 0; i < 4096 + 16384; i++) {
+        uint64_t a = random_word(&state), b = random_word(&state), out[2];
+        if(i < 4096)
+            a = ((uint64_t)(i & 1) << 63) | ((uint64_t)(i / 2) << 52) |
+                (a & UINT64_C(0x000fffffffffffff));
+        evaluate(f, a, b, out);
+        invariants(f, a, b, out);
+        for(int j = 0; j < f->outputs; j++)
+            hash = hash_word(hash, signature_word(out[j]));
+        if(f->op >= T_exp && f->op <= T_pow) {
+            double bounded = (double)(a >> 32) * 0x1p-21 - 1024.0;
+            if(f->op == T_exp10) bounded *= 0.25;
+            if(f->op == T_pow) {
+                a = UINT64_C(0x3ff0000000000000) + (a & 4095);
+                b = pk_dmath_bits(bounded * 0x1p40);
+            } else
+                a = pk_dmath_bits(bounded);
+        } else if(f->op == T_asin || f->op == T_acos) {
+            a = pk_dmath_bits((double)(a >> 11) * 0x1p-52 - 1.0);
+        } else if(f->op >= T_log && f->op <= T_log_base) {
+            a &= magnitude_mask;
+            b &= magnitude_mask;
+        } else
+            continue;
+        evaluate(f, a, b, out);
+        invariants(f, a, b, out);
+        for(int j = 0; j < f->outputs; j++)
+            hash = hash_word(hash, signature_word(out[j]));
+    }
+    return hash;
+}
+
+static void run(const Function* f, const char* directory, int probe) {
+    int before = failures;
+    uint64_t frozen = 0;
+    unsigned count = named_cases(f, directory, probe, &frozen);
+    uint64_t actual = sweep(f);
+    if(probe)
+        printf("SWEEP %s %016" PRIx64 "\n", f->name, actual);
+    else if(actual != frozen)
+        mismatch(f, "sweep", "fingerprint", 0, 0, actual, frozen);
+    if(f->rounding_independent) {
+        const int modes[] = {FE_DOWNWARD, FE_UPWARD, FE_TOWARDZERO};
+        for(unsigned i = 0; i < sizeof(modes) / sizeof(*modes); i++) {
+            if(fesetround(modes[i]) != 0) {
+                fputs("fesetround failed\n", stderr);
+                exit(1);
+            }
+            named_cases(f, directory, probe ? 2 : 0, &frozen);
+            uint64_t directed = sweep(f);
+            if(directed != actual)
+                mismatch(f, "sweep", "rounding mode dependence", modes[i], 0, directed, actual);
+        }
+        if(fesetround(FE_TONEAREST) != 0) {
+            fputs("cannot restore rounding\n", stderr);
+            exit(1);
+        }
+    }
+    printf("%s %s/%s: %u named cases, sweep=%016" PRIx64 ", %d rounding mode(s)\n",
+           failures == before ? "PASS" : "FAIL",
+           f->category,
+           f->name,
+           count,
+           actual,
+           f->rounding_independent ? 4 : 1);
+}
+
+int main(int argc, char** argv) {
+    const char* directory = "tests/dmath/cases";
+    const char* only = NULL;
+    int probe = 0, list = 0, ran = 0;
+    for(int i = 1; i < argc; i++) {
+        if(strcmp(argv[i], "--cases") == 0 && i + 1 < argc)
+            directory = argv[++i];
+        else if(strcmp(argv[i], "--probe") == 0)
+            probe = 1;
+        else if(strcmp(argv[i], "--list") == 0)
+            list = 1;
+        else if(argv[i][0] != '-' && !only)
+            only = argv[i];
+        else {
+            fputs("Usage: test_dmath [--cases DIR] [--list] [--probe] [FUNCTION]\n", stderr);
+            return 1;
+        }
+    }
+    if(fegetround() != FE_TONEAREST) {
+        fputs("dmath requires nearest-even\n", stderr);
+        return 1;
+    }
+    volatile double tiny = pk_dmath_from_bits(3);
+    volatile double normal = pk_dmath_from_bits(UINT64_C(0x0010000000000000));
+    if(pk_dmath_bits(tiny + tiny) != 6 ||
+       pk_dmath_bits(normal * 0.25) != UINT64_C(0x0004000000000000)) {
+        fputs("dmath requires gradual underflow (FTZ/DAZ disabled)\n", stderr);
+        return 1;
+    }
+    for(unsigned i = 0; i < sizeof(functions) / sizeof(*functions); i++) {
+        const Function* f = &functions[i];
+        if(only && strcmp(f->name, only) != 0) continue;
+        if(list)
+            printf("%s/%s\n", f->category, f->name);
+        else
+            run(f, directory, probe);
+        ran++;
+    }
+    if(!ran) {
+        fprintf(stderr, "Unknown dmath function: %s\n", only);
+        return 1;
+    }
+    if(failures) fprintf(stderr, "%d dmath check(s) failed\n", failures);
+    return failures ? 1 : 0;
+}

+ 0 - 222
tests/930_deterministic_float.py

@@ -1,222 +0,0 @@
-import math
-import pkpy
-
-config = pkpy.configmacros
-if config["PK_ENABLE_DETERMINISM"] == 0:
-    exit(0)
-    
-def assertEqual(a, b):
-    if a == b:
-        return
-    print(f'{a} != {b} ({a-b})')
-    raise AssertionError
-
-# test constants
-assertEqual(math.pi, 3.14159265358979323846)
-assertEqual(math.e, 2.7182818284590452354)
-assert math.inf, math.inf
-assert math.nan != math.nan
-
-# test ceil
-assert math.ceil(math.pi) == 4
-assert math.ceil(-math.e) == -2
-
-# test floor
-assert math.floor(math.pi) == 3
-assert math.floor(-math.e) == -3
-
-# test trunc
-assert math.trunc(-math.e) == -2
-assert math.trunc(3.999) == 3
-
-# test fabs
-assertEqual(math.fabs(math.pi), 3.14159265358979323846)
-assertEqual(math.fabs(-math.pi), 3.14159265358979323846)
-
-# test gcd
-assertEqual(math.gcd(10, 5), 5)
-assertEqual(math.gcd(10, 6), 2)
-assertEqual(math.gcd(10, 7), 1)
-assertEqual(math.gcd(10, 10), 10)
-assertEqual(math.gcd(-10, 10), 10)
-
-# test isfinite, isinf, isnan
-assertEqual(math.isfinite(math.pi), True)
-assertEqual(math.isfinite(math.inf), False)
-assertEqual(math.isfinite(math.nan), False)
-assertEqual(math.isinf(math.pi), False)
-assertEqual(math.isinf(math.inf), True)
-assertEqual(math.isinf(math.nan), False)
-assertEqual(math.isnan(math.pi), False)
-assertEqual(math.isnan(math.inf), False)
-assertEqual(math.isnan(math.nan), True)
-
-# test exp
-assertEqual(math.exp(0), 1.0)
-assertEqual(math.exp(1), math.e)
-assertEqual(math.exp(1.5), 4.48168907033806362960604019463)
-assertEqual(math.exp(3), 20.0855369231876608182574273087)
-assertEqual(math.exp(-3), 0.04978706836786396527916309651)
-assertEqual(math.exp(-2.253647), 0.1050155336754953 - 1.387778780781446e-17)
-assertEqual(math.exp(4.729036), 113.186398052200445363268954679)
-
-# test log series
-assertEqual(math.log(0), -math.inf)
-assertEqual(math.log(1), 0.0)
-assertEqual(math.log(2), 0.69314718055994530942)
-assertEqual(math.log(math.e), 1.0)
-assertEqual(math.log(10), 2.30258509299404545700440394284)
-assertEqual(math.log(28.897124), 3.363742074595449)
-assertEqual(math.log2(math.e), 1.4426950408889634074)
-assertEqual(math.log2(78.781291), 6.299781153677818)
-assertEqual(math.log10(math.e), 0.43429448190325182765)
-assertEqual(math.log10(56.907822), 1.755171964426069 + 4.440892098500626e-16)
-
-# test pow
-assertEqual(math.pow(2,2), 4.0)
-assertEqual(math.pow(1.41421356237309504880, 2), 2.0 + 4.440892098500626e-16)
-assertEqual(math.pow(0.70710678118654752440, 2), 0.5000000000000001)
-assertEqual(math.pow(-1.255782,-3), -0.5049603042167915)
-assertEqual(math.pow(6.127042, 4.071529), 1604.40754645674428502388764172)
-
-# test sqrt
-# these match CPython bit-for-bit (hardware sqrt is correctly rounded, see dmath_sqrt)
-assertEqual(math.sqrt(2), 1.4142135623730951)
-assertEqual(math.sqrt(math.pi), 1.7724538509055159)
-assertEqual(math.sqrt(125.872509), 11.21929182257062)
-assertEqual(math.sqrt(1225.296280), 35.00423231553579)
-assertEqual(math.sqrt(0.1), 0.31622776601683794)
-assertEqual(math.sqrt(1e300), 1e150)
-assertEqual(math.sqrt(1.7976931348623157e308), 1.3407807929942596e154)
-# subnormal inputs
-assertEqual(math.sqrt(1e-320), 9.99994433575849e-161)
-assertEqual(math.sqrt(5e-324), 2.2227587494850775e-162)
-# perfect squares must be exact, the old exp/log based sqrt gave sqrt(9) == 2.9999999999999996
-for i in range(2000):
-    assertEqual(math.sqrt(i * i), float(i))
-# special values
-assertEqual(math.sqrt(math.inf), math.inf)
-assertEqual(math.copysign(1.0, math.sqrt(0.0)), 1.0)
-assertEqual(math.copysign(1.0, math.sqrt(-0.0)), -1.0)
-assert math.isnan(math.sqrt(-1))
-assert math.isnan(math.sqrt(-math.inf))
-assert math.isnan(math.sqrt(math.nan))
-
-# test cbrt
-# cbrt is not required by IEEE 754 to be correctly rounded, so unlike sqrt there is
-# no hardware instruction to lean on; these come from the musl port in dmath_zig.c.
-# The cases marked below differ from CPython's math.cbrt by 1 ulp on Windows, where
-# it is the musl port that is correctly rounded and the platform CRT that is not.
-assertEqual(math.cbrt(2), 1.2599210498948732)  # CPython/msvc gives 1.259921049894873
-assertEqual(math.cbrt(3), 1.4422495703074083)
-assertEqual(math.cbrt(10), 2.154434690031884)
-assertEqual(math.cbrt(0.1), 0.4641588833612779)  # CPython/msvc gives 0.464158883361278
-assertEqual(math.cbrt(125.872509), 5.011606490362725)
-assertEqual(math.cbrt(1225.296280), 10.700737364388822)
-assertEqual(math.cbrt(1e300), 1e100)
-assertEqual(math.cbrt(1.7976931348623157e308), 5.643803094122362e102)
-# negative inputs, which the old dmath_pow based cbrt returned nan for
-assertEqual(math.cbrt(-8.0), -2.0)
-assertEqual(math.cbrt(-0.5), -0.7937005259840998)  # CPython/msvc gives -0.7937005259840997
-assertEqual(math.cbrt(-1000.0), -10.0)
-assertEqual(math.cbrt(-1e300), -1e100)
-# subnormal inputs, which the old cbrt got wrong by orders of magnitude
-# because dmath_log2 does not normalize them: cbrt(5e-324) came out as 2.2323972485981933e-103
-assertEqual(math.cbrt(5e-324), 1.7031839360032603e-108)
-assertEqual(math.cbrt(-5e-324), -1.7031839360032603e-108)
-assertEqual(math.cbrt(1e-320), 2.1544266950262728e-107)  # CPython/msvc gives 2.154426695026273e-107
-assertEqual(math.cbrt(2.2250738585072014e-308), 2.812644285236262e-103)  # CPython/msvc gives 2.8126442852362615e-103
-# perfect cubes must be exact; the old cbrt got 1800 of these 2000 wrong,
-# e.g. cbrt(27) == 2.9999999999999996 and cbrt(8) == 1.9999999999999998
-for i in range(2000):
-    assertEqual(math.cbrt(i * i * i), float(i))
-    assertEqual(math.cbrt(-(i * i * i)), -float(i))
-# special values
-assertEqual(math.cbrt(math.inf), math.inf)
-assertEqual(math.cbrt(-math.inf), -math.inf)
-assertEqual(math.copysign(1.0, math.cbrt(0.0)), 1.0)
-assertEqual(math.copysign(1.0, math.cbrt(-0.0)), -1.0)
-assert math.isnan(math.cbrt(math.nan))
-
-# test cos, sin, tan
-assertEqual(math.cos(0), 1.0)
-assertEqual(math.cos(math.pi/2), 6.123233995736766e-17)
-assertEqual(math.cos(math.pi), -1.0)
-assertEqual(math.cos(-11.352808), 0.3496839289707818 - 5.551115123125783e-17)
-assertEqual(math.cos(7.294708), 0.530570640518482)
-assertEqual(math.sin(0), 0.0)
-assertEqual(math.sin(math.pi/2), 1.0)
-assertEqual(math.sin(math.pi), 1.224646799147353e-16 + 2.465190328815662e-32)
-assertEqual(math.sin(-2.837592), -0.2993398018896187)
-assertEqual(math.sin(9.294782), 0.1296301374714747)
-assertEqual(math.tan(0), 0.0)
-assertEqual(math.tan(math.pi/2), 1.633123935319537e+16)
-assertEqual(math.tan(math.pi), -1.224646799147353e-16 - 2.465190328815662e-32)
-assertEqual(math.tan(-4.812975), 9.908188146466314)
-assertEqual(math.tan(1.875814), -3.176189742032396 - 4.440892098500626e-16)
-
-# test acos, asin, atan
-# these match CPython bit-for-bit (ported from Zig, see src/common/dmath_zig.c)
-assertEqual(math.acos(0), 1.5707963267948966)
-assertEqual(math.acos(1), 0.0)
-assertEqual(math.acos(-0.758293), 2.4314869951218965)
-assertEqual(math.acos(0.024758), 1.546035796825635)
-assertEqual(math.asin(0), 0.0)
-assertEqual(math.asin(1), 1.5707963267948966)
-assertEqual(math.asin(-0.225895), -0.22786168657739128)
-assertEqual(math.asin(0.955658), 1.2718861958194234)
-assertEqual(math.atan(0), 0.0)
-assertEqual(math.atan(1), 0.7853981633974483)
-assertEqual(math.atan(-3.758927), -1.3107852846106174)
-assertEqual(math.atan(35.789293), 1.542862277280122)
-
-# test atan2
-assertEqual(math.atan2(math.pi/4, math.pi/4), 0.7853981633974483)
-assertEqual(math.atan2(-math.pi/4, math.pi/4), -0.7853981633974483)
-assertEqual(math.atan2(-math.pi/4, -math.pi/4), -2.356194490192345)
-assertEqual(math.atan2(math.pi/4, -math.pi/4), 2.356194490192345)
-assertEqual(math.atan2(1.573823, 0.685329), 1.160103682924653)
-assertEqual(math.atan2(-0.899663, 0.668972), -0.9314162757114095)
-assertEqual(math.atan2(-0.762894, -0.126497), -1.7351133471732965)
-assertEqual(math.atan2(0.468463, -0.992734), 2.7006834106923736)
-
-# near-vertical vectors used to hit a NaN in the old atan (ratio >= 2^26),
-# which silently turned into direction index 0 for callers
-assertEqual(math.atan2(1.0, 1e-8), 1.5707963167948966)
-assertEqual(math.atan2(1.0, 1e-12), 1.5707963267938967)
-assertEqual(math.atan2(-3.5, 1e-15), -1.5707963267948963)
-
-# test fsum, sum
-fsum_sin = math.fsum([math.sin(i) for i in range(5000)])
-fsum_cos = math.fsum([math.cos(i) for i in range(5000, 9999)])
-assertEqual(fsum_sin, 1.267667771014267 + 2.220446049250313e-16)
-assertEqual(fsum_cos, 1.949547793618193 - 4.440892098500626e-16)
-assertEqual(fsum_sin + fsum_cos, 3.21721556463246)
-sum_sin = sum([math.sin(i) for i in range(5000)])
-sum_cos = sum([math.cos(i) for i in range(5000, 9999)])
-assertEqual(sum_sin, 1.267667771014264 - 2.220446049250313e-16)
-assertEqual(sum_cos, 1.949547793618197 - 4.440892098500626e-16)
-assertEqual(sum_sin + sum_cos, 3.21721556463246 + 4.440892098500626e-16)
-
-# test fmod
-assertEqual(math.fmod(-2.0, 3.0), -2.0)
-assertEqual(math.fmod(2.0, 3.0), 2.0)
-assertEqual(math.fmod(4.0, 3.0), 1.0)
-assertEqual(math.fmod(-4.0, 3.0), -1.0)
-
-# test modf
-x, y = math.modf(math.pi)
-assertEqual(x, 0.14159265358979323846 - 1.110223024625157e-16)
-assertEqual(y, 3.0)
-
-x, y = math.modf(-math.e)
-assertEqual(x, -0.7182818284590451)
-assertEqual(y, -2.0)
-
-# test factorial
-assertEqual(math.factorial(0), 1)
-assertEqual(math.factorial(1), 1)
-assertEqual(math.factorial(2), 2)
-assertEqual(math.factorial(3), 6)
-assertEqual(math.factorial(4), 24)
-assertEqual(math.factorial(5), 120)

+ 229 - 0
tests/930_dmath.py

@@ -0,0 +1,229 @@
+"""Python bindings for the new per-function dmath corpus.
+
+Run from the repository root: main tests/930_dmath.py [function]
+C-only functions (exp2, exp10, sincos, isnormal, fmin, fmax) have their own
+groups in test_dmath. The same frozen cases are used here, without decimal
+parsing or signed-integer overflow during test setup.
+"""
+import math
+import stdc
+import sys
+
+
+_byte_order_probe = stdc.UInt(1)
+_little_endian = stdc.read_bytes(stdc.addressof(_byte_order_probe), 4)[0] == 1
+_hex_digits = '0123456789abcdef'
+
+
+def from_bits(text):
+    raw = bytes([int(text[i:i + 2], 16) for i in range(0, 16, 2)])
+    if _little_endian:
+        raw = raw[::-1]
+    cell = stdc.Double(0.0)
+    stdc.memcpy(stdc.addressof(cell), raw, 8)
+    return cell.value
+
+
+def to_bits(x):
+    cell = stdc.Double(x)
+    raw = stdc.read_bytes(stdc.addressof(cell), 8)
+    if _little_endian:
+        raw = raw[::-1]
+    return ''.join([_hex_digits[b >> 4] + _hex_digits[b & 15] for b in raw])
+
+
+def check_result(actual, expected, context):
+    if expected == 'nan':
+        assert math.isnan(actual), context
+    elif expected == '+inf' or expected == '-inf':
+        assert math.isinf(actual), context
+        assert (actual > 0.0) == (expected == '+inf'), context
+    else:
+        assert to_bits(actual) == expected, (context, to_bits(actual), expected)
+
+
+def raises_type_error(function, *args):
+    try:
+        function(*args)
+    except TypeError:
+        return
+    raise AssertionError('expected TypeError')
+
+
+def check_cases(name, function, arity=1, kind='float'):
+    with open('tests/dmath/cases/' + name + '.txt', 'rt') as handle:
+        lines = handle.read().split('\n')
+    count = 0
+    for line in lines:
+        if not line or line.startswith('#'):
+            continue
+        fields = line.split()
+        label, x_word, y_word, expected, auxiliary = fields[:5]
+        assert expected != 'PENDING', (name, label, 'unreviewed case')
+        x, y = from_bits(x_word), from_bits(y_word)
+        result = function(x) if arity == 1 else function(x, y)
+        context = (name, label, x_word, y_word)
+        if kind == 'bool':
+            assert type(result) is bool, context
+            assert result == bool(int(expected, 16)), context
+        elif kind == 'rounding':
+            want = from_bits(expected) if len(expected) == 16 else math.nan
+            if want >= from_bits('c3e0000000000000') and want < from_bits('43e0000000000000'):
+                assert type(result) is int, context
+                assert result == int(want), context
+            else:
+                assert type(result) is float, context
+                check_result(result, expected, context)
+        elif kind == 'pair':
+            assert type(result) is tuple and len(result) == 2, context
+            check_result(result[0], expected, context)
+            check_result(result[1], auxiliary, context)
+        else:
+            assert type(result) is float, context
+            check_result(result, expected, context)
+        count += 1
+    assert count > 0, name
+    raises_type_error(function)
+    raises_type_error(function, 'not a number')
+    raises_type_error(function, 1.0, 2.0, 3.0)
+    if arity == 2:
+        raises_type_error(function, 1.0, 'not a number')
+    print('PASS math.' + name + ': ' + str(count) + ' named cases')
+
+
+# Classification.
+def test_isfinite():
+    check_cases('isfinite', math.isfinite, kind='bool')
+
+
+def test_isinf():
+    check_cases('isinf', math.isinf, kind='bool')
+
+
+def test_isnan():
+    check_cases('isnan', math.isnan, kind='bool')
+
+
+# Sign operations require exact finite results; NaNs are checked by classification.
+def test_fabs():
+    check_cases('fabs', math.fabs)
+
+
+def test_copysign():
+    check_cases('copysign', math.copysign, 2)
+
+
+# Integral return types and exact int64 arguments belong to the binding layer.
+def check_integer_arguments(function):
+    for x in [9007199254741027, -9007199254741027, 9223372036854775793,
+              -9223372036854775807 - 1]:
+        assert type(function(x)) is int
+        assert function(x) == x
+
+
+def test_ceil():
+    check_cases('ceil', math.ceil, kind='rounding')
+    check_integer_arguments(math.ceil)
+
+
+def test_floor():
+    check_cases('floor', math.floor, kind='rounding')
+    check_integer_arguments(math.floor)
+
+
+def test_trunc():
+    check_cases('trunc', math.trunc, kind='rounding')
+    check_integer_arguments(math.trunc)
+
+
+def test_modf():
+    check_cases('modf', math.modf, kind='pair')
+    assert math.modf(83) == (0.0, 83.0)
+
+
+def test_fmod():
+    check_cases('fmod', math.fmod, 2)
+
+
+# Roots.
+def test_sqrt():
+    check_cases('sqrt', math.sqrt)
+
+
+def test_cbrt():
+    check_cases('cbrt', math.cbrt)
+
+
+# Exponential and logarithmic functions.
+def test_exp():
+    check_cases('exp', math.exp)
+
+
+def test_pow():
+    check_cases('pow', math.pow, 2)
+
+
+def test_log():
+    check_cases('log', math.log)
+
+
+def test_log2():
+    check_cases('log2', math.log2)
+
+
+def test_log10():
+    check_cases('log10', math.log10)
+
+
+def test_log_base():
+    check_cases('log_base', math.log, 2)
+
+
+# Trigonometry.
+def test_sin():
+    check_cases('sin', math.sin)
+
+
+def test_cos():
+    check_cases('cos', math.cos)
+
+
+def test_tan():
+    check_cases('tan', math.tan)
+
+
+# Inverse trigonometry.
+def test_asin():
+    check_cases('asin', math.asin)
+
+
+def test_acos():
+    check_cases('acos', math.acos)
+
+
+def test_atan():
+    check_cases('atan', math.atan)
+
+
+def test_atan2():
+    check_cases('atan2', math.atan2, 2)
+
+
+groups = [
+    ('classification', [test_isfinite, test_isinf, test_isnan]),
+    ('sign', [test_fabs, test_copysign]),
+    ('rounding_and_remainder', [test_ceil, test_floor, test_trunc, test_modf, test_fmod]),
+    ('roots', [test_sqrt, test_cbrt]),
+    ('exponentials', [test_exp, test_pow]),
+    ('logarithms', [test_log, test_log2, test_log10, test_log_base]),
+    ('trigonometry', [test_sin, test_cos, test_tan]),
+    ('inverse_trigonometry', [test_asin, test_acos, test_atan, test_atan2]),
+]
+selected = sys.argv[1] if len(sys.argv) > 1 else None
+ran = 0
+for category, functions in groups:
+    for function in functions:
+        if selected is None or function.__name__ == 'test_' + selected:
+            function()
+            ran += 1
+assert ran > 0, selected

+ 4 - 4
tests/931_math.py

@@ -710,10 +710,10 @@ class MathTests(TestCase):
         # self.assertRaises(ValueError, math.pow, 0., -2.3)
         # self.assertRaises(ValueError, math.pow, 0., -2.3)
         # self.assertRaises(ValueError, math.pow, 0., -3.)
         # self.assertRaises(ValueError, math.pow, 0., -3.)
         # self.assertRaises(ValueError, math.pow, 0., NINF)
         # self.assertRaises(ValueError, math.pow, 0., NINF)
-        self.assertTrue(math.isnan(math.pow(0., -2.)))
-        self.assertTrue(math.isnan(math.pow(0., -2.3)))
-        self.assertTrue(math.isnan(math.pow(0., -3.)))
-        self.assertTrue(math.isnan(math.pow(0., NINF)))
+        self.assertEqual(math.pow(0., -2.), INF)
+        self.assertEqual(math.pow(0., -2.3), INF)
+        self.assertEqual(math.pow(0., -3.), INF)
+        self.assertEqual(math.pow(0., NINF), INF)
 
 
         self.assertTrue(math.isnan(math.pow(0., NAN)))
         self.assertTrue(math.isnan(math.pow(0., NAN)))
 
 

+ 73 - 0
tests/932_dmath_consumers.py

@@ -0,0 +1,73 @@
+"""Fresh integration cases for consumers of dmath, separate from kernel tests."""
+import math
+import cmath
+import operator
+from vmath import vec2
+
+
+def same_float(x, y):
+    if math.isnan(y):
+        assert math.isnan(x)
+    else:
+        assert x == y, (x, y)
+        if y == 0.0:
+            assert math.copysign(1.0, x) == math.copysign(1.0, y)
+
+
+def test_floating_power_entry_points():
+    cases = [(5.1875, -4.75), (-5.1875, 9.0), (-5.1875, 0.75),
+             (-0.0, -9.0), (-0.0, 9.0), (17.0, 8192.0),
+             (17.0, -8192.0), (1.0, math.nan), (math.nan, 0.0)]
+    for x, y in cases:
+        reference = math.pow(x, y)
+        same_float(x ** y, reference)
+        same_float(operator.pow(x, y), reference)
+
+
+def test_integer_power_policy():
+    # Compute reference modular products using small values / signed endpoints.
+    cases = [(3, 39, 4052555153018976267), (-3, 39, -4052555153018976267),
+             (4, 32, 0), (9223372036854775806, 2, 4),
+             (-9223372036854775807, 2, 1)]
+    for x, y, expected in cases:
+        assert x ** y == expected
+        assert type(x ** y) is int
+    try:
+        operator.pow(0, -9)
+        assert False
+    except ZeroDivisionError:
+        pass
+
+
+def test_floating_division_consumers():
+    for x, y in [(139.875, 7.5), (-139.875, 7.5), (139.875, -7.5),
+                 (-139.875, -7.5), (3.125e225, 0.25), (-3.125e225, 0.25)]:
+        quotient, remainder = divmod(x, y)
+        same_float(x // y, quotient)
+        same_float(x % y, remainder)
+        assert quotient == math.floor(quotient)
+        assert quotient * y + remainder == x
+        if remainder:
+            assert math.copysign(1.0, remainder) == math.copysign(1.0, y)
+
+
+def test_complex_and_rotation_consumers():
+    for angle in [0.46875, -27.1875, 7.125e17, -2.6875e211]:
+        sine, cosine = math.sin(angle), math.cos(angle)
+        z = cmath.rect(1.0, angle)
+        same_float(z.real, cosine)
+        same_float(z.imag, sine)
+        z = cmath.exp(complex(0.0, angle))
+        same_float(z.real, cosine)
+        same_float(z.imag, sine)
+        # Vector storage is float32; this checks the combined sincos consumer.
+        rotated = vec2(1.0, 0.0).rotate(angle)
+        assert abs(rotated.x - cosine) <= 6e-8
+        assert abs(rotated.y - sine) <= 6e-8
+    same_float(cmath.exp(complex(707.25, 0.0)).real, math.exp(707.25))
+
+
+test_floating_power_entry_points()
+test_integer_power_policy()
+test_floating_division_consumers()
+test_complex_and_rotation_consumers()

+ 148 - 0
tests/dmath/README.md

@@ -0,0 +1,148 @@
+# Deterministic math tests
+
+The suite covers every public function declared in
+`include/pocketpy/common/dmath.h`. It replaces the old mixed Python assertions,
+exponential/trigonometric vector headers, generators, and aggregate fingerprints.
+The general math compatibility tests in `tests/704_math.py` and
+`tests/931_math.py` are separate from this determinism suite.
+
+## Find a function's cases
+
+Each function has one file in `tests/dmath/cases/`, for example `sqrt.txt`,
+`atan2.txt`, or `modf.txt`. Each row has a descriptive case name, two exact input
+words, frozen finite output words, independently calculated references, and an
+accuracy allowance. Nonfinite expectations are the readable tokens `nan`,
+`+inf`, and `-inf`; their bit patterns are not compared. Hexadecimal
+floating-point inputs appear beside each row.
+`modf` orders its outputs as (fraction, integral); `sincos` uses (sine, cosine).
+Classification results are integer 0/1, not binary64 encodings of 0.0/1.0.
+
+| Category | Function groups | Main coverage |
+| --- | --- | --- |
+| Classification | `isfinite`, `isinf`, `isnan`, `isnormal` | All exponent classes, signs, quiet/signaling NaNs |
+| Sign and ordering | `fabs`, `copysign`, `fmin`, `fmax` | Finite sign changes, NaN classification, NaNs in either operand, zero ties |
+| Rounding and remainder | `ceil`, `floor`, `trunc`, `modf`, `fmod` | Fraction boundaries, word/exponent transitions, huge quotients, both outputs |
+| Roots | `sqrt`, `cbrt` | Subnormals, exact roots, exponent classes, software sqrt |
+| Exponentials | `exp`, `exp2`, `exp10`, `pow` | Reduction/table boundaries, underflow ties, overflow, parity, near-one bases |
+| Logarithms | `log`, `log2`, `log10`, `log_base` | Normalization, neighbors of one, poles, invalid bases |
+| Trigonometry | `sin`, `cos`, `tan`, `sincos` | Tiny inputs, argument-reduction boundaries, large finite angles, tangent poles |
+| Inverse trigonometry | `asin`, `acos`, `atan`, `atan2` | Domain endpoints, polynomial interval boundaries, quadrants, axes, extreme ratios |
+
+The new design contains 1,250 named cases across 31 functions. Mandatory IEEE
+endpoints such as signed zero and infinity naturally recur; arbitrary inputs,
+case organization, random streams, and fingerprints were designed anew.
+
+## Run
+
+From the repository root:
+
+```sh
+cmake -S . -B build -DPK_BUILD_MATH_TESTS=ON -DPK_ENABLE_DETERMINISM=ON
+cmake --build build --config Release
+ctest --test-dir build -C Release --output-on-failure
+
+# Select a function, or list every group (Windows executables may be in Release/).
+build/test_dmath --list
+build/test_dmath atan2
+build/test_dmath --cases /absolute/path/to/tests/dmath/cases sqrt
+
+# Python bindings, optionally selecting one function.
+./main tests/930_dmath.py
+./main tests/930_dmath.py modf
+./main tests/932_dmath_consumers.py
+
+# Verify the independent references and complete public-function coverage.
+python scripts/dmath/generate.py --check
+```
+
+CTest reports each function separately, plus `dmath.sqrt_software`. The latter
+forces the integer-arithmetic sqrt fallback and checks the same expected bits
+as hardware sqrt. Normal test execution uses neither `assert` in C nor the
+host libm as a numerical oracle; Release/NDEBUG builds keep all checks active.
+
+Python tests read the same case files. Byte copies through `stdc` transport
+binary64 values without the integer or decimal parsers. Some ABIs quiet
+signaling NaNs in transit; only their classification is asserted.
+Python rounding return types and exact integer
+arguments are checked separately. The six internal-only functions (`exp2`,
+`exp10`, `sincos`, `isnormal`, `fmin`, `fmax`) are tested through the C runner.
+Power operators, divmod, complex exponentials, and vector rotations have fresh
+integration cases in `932_dmath_consumers.py`.
+
+## Three distinct checks
+
+1. **Accuracy and special-value semantics.** `scripts/dmath/oracle.py` uses
+   exact integers/Fractions for bit operations, rounding, remainders, and
+   integer powers. Other references use Decimal roots/exp/log, Machin's formula
+   for pi, angle reduction and convergent series. Rounded answers must agree
+   at both 430 and 570 decimal digits. Exact rational evaluation resolves
+   binary halfway cases, including `exp2(-1075)`. NaNs have classification
+   checks; infinities have classification/sign checks. Signed zero and exact
+   finite operations have bitwise checks. Approximation allowances are listed
+   in `scripts/dmath/cases.py`; they are test budgets, not global error proofs.
+2. **Frozen finite output bits.** Every named case also checks the reviewed
+   finite result exactly, including both outputs of `modf`/`sincos`. The initial
+   baseline was accepted only after GCC, Clang, and MSVC independently passed
+   the accuracy checks and produced identical results. All observed nonzero
+   errors in this named corpus were one ULP. Tolerances never weaken this
+   exact-output check.
+3. **Per-function sweeps.** Each function gets its own SplitMix64 stream:
+   every exponent field with both signs and fresh significands, followed by
+   16,384 full-range inputs. Exponential, logarithmic and inverse-trigonometric
+   groups add inputs in useful finite domains. Each function has a separate
+   endian-independent fingerprint. Classification and bit operations have
+   exact runtime references; other invariants include min/max commutativity,
+   remainder range/sign, modf recomposition, and sincos
+   agreement with separate calls. These sweeps detect deterministic changes;
+   they do not establish random-input accuracy against a high-precision oracle.
+   NaN results are mapped to one test-only token before hashing, so differences
+   in NaN sign, payload or quiet bit cannot fail a determinism check. Infinity
+   tokens distinguish signs. Finite values, including signed zero, are unchanged.
+
+Classification, sign/order, rounding, and remainder groups run under all four
+rounding modes. Other computations require nearest-even. Entry checks detect
+unsupported rounding and FTZ/DAZ environments. No test or kernel repairs the
+embedding application's floating-point environment.
+
+## Updating cases
+
+Edit the named function in `scripts/dmath/cases.py`, then run the generator.
+Existing frozen words are preserved only when the case name and both inputs
+match. New cases are marked `PENDING`; normal tests fail until reviewed. The
+generator never invokes dmath or automatically recalibrates expected bits.
+`test_dmath --probe [function]` prints candidate words/fingerprints while still
+checking independent references and invariants. It is a diagnostic, not a
+passing determinism test; CI always runs without `--probe`.
+
+Review numerical changes before updating frozen words. Compare independent
+compiler results, run the accuracy checks and sanitizers, and inspect every
+changed output. Never regenerate a baseline merely to turn a failure green.
+
+## Implementation audit (2026-10-03)
+
+| Area | Result |
+| --- | --- |
+| `isfinite`, `isinf`, `isnan`, `isnormal` | Bit classification; full exponent/sign coverage. No arithmetic on NaNs. |
+| `fabs`, `copysign` | Finite sign-bit operations retained. MSVC x86 may quiet signaling NaNs through its return ABI; NaN encoding is explicitly outside the determinism contract. No ABI workaround or new normalization. |
+| `fmin`, `fmax` | Fixed single-NaN handling and operand-order-dependent zero ties. Two NaNs produce NaN. Minimum prefers -0; maximum prefers +0. |
+| `ceil`, `floor`, `trunc` | Unsigned masks, no out-of-range float-to-int casts. All finite magnitudes supported. |
+| `modf`, `fmod` | Remainder algorithms retained. Both modf outputs and full finite exponent ranges are covered; NaN results are checked by classification. |
+| `sqrt` | Hardware implementation retained. Software/hardware results use the same corpus and finite-result fingerprint. |
+| `cbrt`, `asin`, `acos`, `atan`, `atan2` | Legacy algorithms retained. Boundary/accuracy tests cover these formerly omitted C groups. |
+| OpenLibm exp/log/pow/trig kernels | Reviewed special branches, shift/cast bounds, subnormal paths and reduction dependencies. New cases and full UBSan pass; no approximation coefficients changed. |
+| NaN/Inf constants | Replaced overflow-expression construction with bit construction: GCC directed-rounding tests found that the former NaN expression could evaluate to finite zero. This fixes classification, without requiring any particular NaN output bits. |
+| Build contract | Format, fast-math and excess-precision checks apply to all kernels. Floating-point options belong to CMake; no compiler-specific FP pragmas or local control macros. |
+| `math.modf` binding | Fixed direct float-storage access for integer/non-numeric arguments; use the existing checked numeric conversion. |
+
+The contract assumes IEEE binary64, nearest-even, gradual underflow, disabled
+FP traps, and the configured noncontracting arithmetic. `errno`, FP exception
+flags, and NaN payload propagation by arithmetic functions are outside it.
+There is no portable preprocessor test for `-ffp-contract`; the build must pass
+the correct option. CPU FMA availability alone does not mean contraction is on.
+
+The legacy Zig/musl source links do not identify the original upstream revision;
+this remains a provenance limitation, not a build-time source dependency. The
+OpenLibm source revision is pinned separately in `3rd/openlibm/README.md`.
+The integer-prefix parser overflow discussed earlier is outside dmath and is
+not changed here. The new corpus deliberately transports binary64 words so a
+parser failure cannot hide or imitate a math-kernel failure.

+ 44 - 0
tests/dmath/cases/acos.txt

@@ -0,0 +1,44 @@
+# dmath_acos
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep 109aa863152e16cb
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+positive_zero 0000000000000000 0000000000000000 3ff921fb54442d18 0000000000000000 3ff921fb54442d18 0000000000000000 1 # x=0x0.0p+0 y=0x0.0p+0
+negative_zero 8000000000000000 0000000000000000 3ff921fb54442d18 0000000000000000 3ff921fb54442d18 0000000000000000 1 # x=-0x0.0p+0 y=0x0.0p+0
+least_subnormal 0000000000000001 0000000000000000 3ff921fb54442d18 0000000000000000 3ff921fb54442d18 0000000000000000 1 # x=0x0.0000000000001p-1022 y=0x0.0p+0
+negative_least_subnormal 8000000000000001 0000000000000000 3ff921fb54442d18 0000000000000000 3ff921fb54442d18 0000000000000000 1 # x=-0x0.0000000000001p-1022 y=0x0.0p+0
+third_subnormal 0000000000000003 0000000000000000 3ff921fb54442d18 0000000000000000 3ff921fb54442d18 0000000000000000 1 # x=0x0.0000000000003p-1022 y=0x0.0p+0
+negative_third_subnormal 8000000000000003 0000000000000000 3ff921fb54442d18 0000000000000000 3ff921fb54442d18 0000000000000000 1 # x=-0x0.0000000000003p-1022 y=0x0.0p+0
+largest_subnormal 000fffffffffffff 0000000000000000 3ff921fb54442d18 0000000000000000 3ff921fb54442d18 0000000000000000 1 # x=0x0.fffffffffffffp-1022 y=0x0.0p+0
+negative_largest_subnormal 800fffffffffffff 0000000000000000 3ff921fb54442d18 0000000000000000 3ff921fb54442d18 0000000000000000 1 # x=-0x0.fffffffffffffp-1022 y=0x0.0p+0
+least_normal 0010000000000000 0000000000000000 3ff921fb54442d18 0000000000000000 3ff921fb54442d18 0000000000000000 1 # x=0x1.0000000000000p-1022 y=0x0.0p+0
+negative_least_normal 8010000000000000 0000000000000000 3ff921fb54442d18 0000000000000000 3ff921fb54442d18 0000000000000000 1 # x=-0x1.0000000000000p-1022 y=0x0.0p+0
+largest_finite 7fefffffffffffff 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=0x1.fffffffffffffp+1023 y=0x0.0p+0
+negative_largest_finite ffefffffffffffff 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=-0x1.fffffffffffffp+1023 y=0x0.0p+0
+positive_infinity 7ff0000000000000 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=inf y=0x0.0p+0
+negative_infinity fff0000000000000 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=-inf y=0x0.0p+0
+quiet_nan_payload 7ff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+negative_quiet_nan_payload fff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+signaling_nan_payload 7ff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+negative_signaling_nan_payload fff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+domain_endpoint_below 3fefffffffffffff 0000000000000000 3e50000000000000 0000000000000000 3e50000000000000 0000000000000000 1 # x=0x1.fffffffffffffp-1 y=0x0.0p+0
+domain_endpoint_at 3ff0000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 1 # x=0x1.0000000000000p+0 y=0x0.0p+0
+domain_endpoint_above 3ff0000000000001 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=0x1.0000000000001p+0 y=0x0.0p+0
+negative_domain_endpoint_below bfefffffffffffff 0000000000000000 400921fb52442d18 0000000000000000 400921fb52442d18 0000000000000000 1 # x=-0x1.fffffffffffffp-1 y=0x0.0p+0
+negative_domain_endpoint_at bff0000000000000 0000000000000000 400921fb54442d18 0000000000000000 400921fb54442d18 0000000000000000 1 # x=-0x1.0000000000000p+0 y=0x0.0p+0
+negative_domain_endpoint_above bff0000000000001 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=-0x1.0000000000001p+0 y=0x0.0p+0
+half_interval_below 3fdfffffffffffff 0000000000000000 3ff0c152382d7366 0000000000000000 3ff0c152382d7366 0000000000000000 1 # x=0x1.fffffffffffffp-2 y=0x0.0p+0
+half_interval_at 3fe0000000000000 0000000000000000 3ff0c152382d7366 0000000000000000 3ff0c152382d7366 0000000000000000 1 # x=0x1.0000000000000p-1 y=0x0.0p+0
+half_interval_above 3fe0000000000001 0000000000000000 3ff0c152382d7365 0000000000000000 3ff0c152382d7365 0000000000000000 1 # x=0x1.0000000000001p-1 y=0x0.0p+0
+negative_half_interval_below bfdfffffffffffff 0000000000000000 4000c152382d7365 0000000000000000 4000c152382d7365 0000000000000000 1 # x=-0x1.fffffffffffffp-2 y=0x0.0p+0
+negative_half_interval_at bfe0000000000000 0000000000000000 4000c152382d7366 0000000000000000 4000c152382d7366 0000000000000000 1 # x=-0x1.0000000000000p-1 y=0x0.0p+0
+negative_half_interval_above bfe0000000000001 0000000000000000 4000c152382d7366 0000000000000000 4000c152382d7366 0000000000000000 1 # x=-0x1.0000000000001p-1 y=0x0.0p+0
+tiny_cutoff_below 3c5fffffffffffff 0000000000000000 3ff921fb54442d18 0000000000000000 3ff921fb54442d18 0000000000000000 1 # x=0x1.fffffffffffffp-58 y=0x0.0p+0
+tiny_cutoff_at 3c60000000000000 0000000000000000 3ff921fb54442d18 0000000000000000 3ff921fb54442d18 0000000000000000 1 # x=0x1.0000000000000p-57 y=0x0.0p+0
+tiny_cutoff_above 3c60000000000001 0000000000000000 3ff921fb54442d18 0000000000000000 3ff921fb54442d18 0000000000000000 1 # x=0x1.0000000000001p-57 y=0x0.0p+0
+negative_tiny_cutoff_below bc5fffffffffffff 0000000000000000 3ff921fb54442d18 0000000000000000 3ff921fb54442d18 0000000000000000 1 # x=-0x1.fffffffffffffp-58 y=0x0.0p+0
+negative_tiny_cutoff_at bc60000000000000 0000000000000000 3ff921fb54442d18 0000000000000000 3ff921fb54442d18 0000000000000000 1 # x=-0x1.0000000000000p-57 y=0x0.0p+0
+negative_tiny_cutoff_above bc60000000000001 0000000000000000 3ff921fb54442d18 0000000000000000 3ff921fb54442d18 0000000000000000 1 # x=-0x1.0000000000001p-57 y=0x0.0p+0
+interior_positive 3fd2000000000000 0000000000000000 3ff4923a0b52b60e 0000000000000000 3ff4923a0b52b60e 0000000000000000 1 # x=0x1.2000000000000p-2 y=0x0.0p+0
+interior_negative bfd2000000000000 0000000000000000 3ffdb1bc9d35a423 0000000000000000 3ffdb1bc9d35a423 0000000000000000 1 # x=-0x1.2000000000000p-2 y=0x0.0p+0

+ 44 - 0
tests/dmath/cases/asin.txt

@@ -0,0 +1,44 @@
+# dmath_asin
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep deb9ff6e67ac85b5
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+positive_zero 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 1 # x=0x0.0p+0 y=0x0.0p+0
+negative_zero 8000000000000000 0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 1 # x=-0x0.0p+0 y=0x0.0p+0
+least_subnormal 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 1 # x=0x0.0000000000001p-1022 y=0x0.0p+0
+negative_least_subnormal 8000000000000001 0000000000000000 8000000000000001 0000000000000000 8000000000000001 0000000000000000 1 # x=-0x0.0000000000001p-1022 y=0x0.0p+0
+third_subnormal 0000000000000003 0000000000000000 0000000000000003 0000000000000000 0000000000000003 0000000000000000 1 # x=0x0.0000000000003p-1022 y=0x0.0p+0
+negative_third_subnormal 8000000000000003 0000000000000000 8000000000000003 0000000000000000 8000000000000003 0000000000000000 1 # x=-0x0.0000000000003p-1022 y=0x0.0p+0
+largest_subnormal 000fffffffffffff 0000000000000000 000fffffffffffff 0000000000000000 000fffffffffffff 0000000000000000 1 # x=0x0.fffffffffffffp-1022 y=0x0.0p+0
+negative_largest_subnormal 800fffffffffffff 0000000000000000 800fffffffffffff 0000000000000000 800fffffffffffff 0000000000000000 1 # x=-0x0.fffffffffffffp-1022 y=0x0.0p+0
+least_normal 0010000000000000 0000000000000000 0010000000000000 0000000000000000 0010000000000000 0000000000000000 1 # x=0x1.0000000000000p-1022 y=0x0.0p+0
+negative_least_normal 8010000000000000 0000000000000000 8010000000000000 0000000000000000 8010000000000000 0000000000000000 1 # x=-0x1.0000000000000p-1022 y=0x0.0p+0
+largest_finite 7fefffffffffffff 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=0x1.fffffffffffffp+1023 y=0x0.0p+0
+negative_largest_finite ffefffffffffffff 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=-0x1.fffffffffffffp+1023 y=0x0.0p+0
+positive_infinity 7ff0000000000000 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=inf y=0x0.0p+0
+negative_infinity fff0000000000000 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=-inf y=0x0.0p+0
+quiet_nan_payload 7ff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+negative_quiet_nan_payload fff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+signaling_nan_payload 7ff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+negative_signaling_nan_payload fff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+domain_endpoint_below 3fefffffffffffff 0000000000000000 3ff921fb50442d18 0000000000000000 3ff921fb50442d18 0000000000000000 1 # x=0x1.fffffffffffffp-1 y=0x0.0p+0
+domain_endpoint_at 3ff0000000000000 0000000000000000 3ff921fb54442d18 0000000000000000 3ff921fb54442d18 0000000000000000 1 # x=0x1.0000000000000p+0 y=0x0.0p+0
+domain_endpoint_above 3ff0000000000001 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=0x1.0000000000001p+0 y=0x0.0p+0
+negative_domain_endpoint_below bfefffffffffffff 0000000000000000 bff921fb50442d18 0000000000000000 bff921fb50442d18 0000000000000000 1 # x=-0x1.fffffffffffffp-1 y=0x0.0p+0
+negative_domain_endpoint_at bff0000000000000 0000000000000000 bff921fb54442d18 0000000000000000 bff921fb54442d18 0000000000000000 1 # x=-0x1.0000000000000p+0 y=0x0.0p+0
+negative_domain_endpoint_above bff0000000000001 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=-0x1.0000000000001p+0 y=0x0.0p+0
+half_interval_below 3fdfffffffffffff 0000000000000000 3fe0c152382d7365 0000000000000000 3fe0c152382d7365 0000000000000000 1 # x=0x1.fffffffffffffp-2 y=0x0.0p+0
+half_interval_at 3fe0000000000000 0000000000000000 3fe0c152382d7366 0000000000000000 3fe0c152382d7366 0000000000000000 1 # x=0x1.0000000000000p-1 y=0x0.0p+0
+half_interval_above 3fe0000000000001 0000000000000000 3fe0c152382d7367 0000000000000000 3fe0c152382d7367 0000000000000000 1 # x=0x1.0000000000001p-1 y=0x0.0p+0
+negative_half_interval_below bfdfffffffffffff 0000000000000000 bfe0c152382d7365 0000000000000000 bfe0c152382d7365 0000000000000000 1 # x=-0x1.fffffffffffffp-2 y=0x0.0p+0
+negative_half_interval_at bfe0000000000000 0000000000000000 bfe0c152382d7366 0000000000000000 bfe0c152382d7366 0000000000000000 1 # x=-0x1.0000000000000p-1 y=0x0.0p+0
+negative_half_interval_above bfe0000000000001 0000000000000000 bfe0c152382d7367 0000000000000000 bfe0c152382d7367 0000000000000000 1 # x=-0x1.0000000000001p-1 y=0x0.0p+0
+near_endpoint_formula_below 3fef3332ffffffff 0000000000000000 3ff58c2ae9ab49e8 0000000000000000 3ff58c2ae9ab49e7 0000000000000000 1 # x=0x1.f3332ffffffffp-1 y=0x0.0p+0
+near_endpoint_formula_at 3fef333300000000 0000000000000000 3ff58c2ae9ab49e9 0000000000000000 3ff58c2ae9ab49ea 0000000000000000 1 # x=0x1.f333300000000p-1 y=0x0.0p+0
+near_endpoint_formula_above 3fef333300000001 0000000000000000 3ff58c2ae9ab49ec 0000000000000000 3ff58c2ae9ab49ec 0000000000000000 1 # x=0x1.f333300000001p-1 y=0x0.0p+0
+negative_near_endpoint_formula_below bfef3332ffffffff 0000000000000000 bff58c2ae9ab49e8 0000000000000000 bff58c2ae9ab49e7 0000000000000000 1 # x=-0x1.f3332ffffffffp-1 y=0x0.0p+0
+negative_near_endpoint_formula_at bfef333300000000 0000000000000000 bff58c2ae9ab49e9 0000000000000000 bff58c2ae9ab49ea 0000000000000000 1 # x=-0x1.f333300000000p-1 y=0x0.0p+0
+negative_near_endpoint_formula_above bfef333300000001 0000000000000000 bff58c2ae9ab49ec 0000000000000000 bff58c2ae9ab49ec 0000000000000000 1 # x=-0x1.f333300000001p-1 y=0x0.0p+0
+interior_positive 3fe7000000000000 0000000000000000 3fe9aa01babef75e 0000000000000000 3fe9aa01babef75e 0000000000000000 1 # x=0x1.7000000000000p-1 y=0x0.0p+0
+interior_negative bfe7000000000000 0000000000000000 bfe9aa01babef75e 0000000000000000 bfe9aa01babef75e 0000000000000000 1 # x=-0x1.7000000000000p-1 y=0x0.0p+0

+ 62 - 0
tests/dmath/cases/atan.txt

@@ -0,0 +1,62 @@
+# dmath_atan
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep 9b69ac15da362a74
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+positive_zero 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 1 # x=0x0.0p+0 y=0x0.0p+0
+negative_zero 8000000000000000 0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 1 # x=-0x0.0p+0 y=0x0.0p+0
+least_subnormal 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 1 # x=0x0.0000000000001p-1022 y=0x0.0p+0
+negative_least_subnormal 8000000000000001 0000000000000000 8000000000000001 0000000000000000 8000000000000001 0000000000000000 1 # x=-0x0.0000000000001p-1022 y=0x0.0p+0
+third_subnormal 0000000000000003 0000000000000000 0000000000000003 0000000000000000 0000000000000003 0000000000000000 1 # x=0x0.0000000000003p-1022 y=0x0.0p+0
+negative_third_subnormal 8000000000000003 0000000000000000 8000000000000003 0000000000000000 8000000000000003 0000000000000000 1 # x=-0x0.0000000000003p-1022 y=0x0.0p+0
+largest_subnormal 000fffffffffffff 0000000000000000 000fffffffffffff 0000000000000000 000fffffffffffff 0000000000000000 1 # x=0x0.fffffffffffffp-1022 y=0x0.0p+0
+negative_largest_subnormal 800fffffffffffff 0000000000000000 800fffffffffffff 0000000000000000 800fffffffffffff 0000000000000000 1 # x=-0x0.fffffffffffffp-1022 y=0x0.0p+0
+least_normal 0010000000000000 0000000000000000 0010000000000000 0000000000000000 0010000000000000 0000000000000000 1 # x=0x1.0000000000000p-1022 y=0x0.0p+0
+negative_least_normal 8010000000000000 0000000000000000 8010000000000000 0000000000000000 8010000000000000 0000000000000000 1 # x=-0x1.0000000000000p-1022 y=0x0.0p+0
+largest_finite 7fefffffffffffff 0000000000000000 3ff921fb54442d18 0000000000000000 3ff921fb54442d18 0000000000000000 1 # x=0x1.fffffffffffffp+1023 y=0x0.0p+0
+negative_largest_finite ffefffffffffffff 0000000000000000 bff921fb54442d18 0000000000000000 bff921fb54442d18 0000000000000000 1 # x=-0x1.fffffffffffffp+1023 y=0x0.0p+0
+positive_infinity 7ff0000000000000 0000000000000000 3ff921fb54442d18 0000000000000000 3ff921fb54442d18 0000000000000000 1 # x=inf y=0x0.0p+0
+negative_infinity fff0000000000000 0000000000000000 bff921fb54442d18 0000000000000000 bff921fb54442d18 0000000000000000 1 # x=-inf y=0x0.0p+0
+quiet_nan_payload 7ff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+negative_quiet_nan_payload fff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+signaling_nan_payload 7ff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+negative_signaling_nan_payload fff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+ordinary_positive 4022a00000000000 0000000000000000 3ff76bd26302c625 0000000000000000 3ff76bd26302c625 0000000000000000 1 # x=0x1.2a00000000000p+3 y=0x0.0p+0
+ordinary_negative c022a00000000000 0000000000000000 bff76bd26302c625 0000000000000000 bff76bd26302c625 0000000000000000 1 # x=-0x1.2a00000000000p+3 y=0x0.0p+0
+tiny_cutoff_below 3e3fffffffffffff 0000000000000000 3e3fffffffffffff 0000000000000000 3e3fffffffffffff 0000000000000000 1 # x=0x1.fffffffffffffp-28 y=0x0.0p+0
+tiny_cutoff_at 3e40000000000000 0000000000000000 3e40000000000000 0000000000000000 3e40000000000000 0000000000000000 1 # x=0x1.0000000000000p-27 y=0x0.0p+0
+tiny_cutoff_above 3e40000000000001 0000000000000000 3e40000000000001 0000000000000000 3e40000000000001 0000000000000000 1 # x=0x1.0000000000001p-27 y=0x0.0p+0
+negative_tiny_cutoff_below be3fffffffffffff 0000000000000000 be3fffffffffffff 0000000000000000 be3fffffffffffff 0000000000000000 1 # x=-0x1.fffffffffffffp-28 y=0x0.0p+0
+negative_tiny_cutoff_at be40000000000000 0000000000000000 be40000000000000 0000000000000000 be40000000000000 0000000000000000 1 # x=-0x1.0000000000000p-27 y=0x0.0p+0
+negative_tiny_cutoff_above be40000000000001 0000000000000000 be40000000000001 0000000000000000 be40000000000001 0000000000000000 1 # x=-0x1.0000000000001p-27 y=0x0.0p+0
+first_interval_below 3fdbffffffffffff 0000000000000000 3fda64eec3cc23fc 0000000000000000 3fda64eec3cc23fc 0000000000000000 1 # x=0x1.bffffffffffffp-2 y=0x0.0p+0
+first_interval_at 3fdc000000000000 0000000000000000 3fda64eec3cc23fd 0000000000000000 3fda64eec3cc23fd 0000000000000000 1 # x=0x1.c000000000000p-2 y=0x0.0p+0
+first_interval_above 3fdc000000000001 0000000000000000 3fda64eec3cc23fe 0000000000000000 3fda64eec3cc23fe 0000000000000000 1 # x=0x1.c000000000001p-2 y=0x0.0p+0
+negative_first_interval_below bfdbffffffffffff 0000000000000000 bfda64eec3cc23fc 0000000000000000 bfda64eec3cc23fc 0000000000000000 1 # x=-0x1.bffffffffffffp-2 y=0x0.0p+0
+negative_first_interval_at bfdc000000000000 0000000000000000 bfda64eec3cc23fd 0000000000000000 bfda64eec3cc23fd 0000000000000000 1 # x=-0x1.c000000000000p-2 y=0x0.0p+0
+negative_first_interval_above bfdc000000000001 0000000000000000 bfda64eec3cc23fe 0000000000000000 bfda64eec3cc23fe 0000000000000000 1 # x=-0x1.c000000000001p-2 y=0x0.0p+0
+second_interval_below 3fe5ffffffffffff 0000000000000000 3fe345f01cce37ba 0000000000000000 3fe345f01cce37bb 0000000000000000 1 # x=0x1.5ffffffffffffp-1 y=0x0.0p+0
+second_interval_at 3fe6000000000000 0000000000000000 3fe345f01cce37bb 0000000000000000 3fe345f01cce37bb 0000000000000000 1 # x=0x1.6000000000000p-1 y=0x0.0p+0
+second_interval_above 3fe6000000000001 0000000000000000 3fe345f01cce37bc 0000000000000000 3fe345f01cce37bc 0000000000000000 1 # x=0x1.6000000000001p-1 y=0x0.0p+0
+negative_second_interval_below bfe5ffffffffffff 0000000000000000 bfe345f01cce37ba 0000000000000000 bfe345f01cce37bb 0000000000000000 1 # x=-0x1.5ffffffffffffp-1 y=0x0.0p+0
+negative_second_interval_at bfe6000000000000 0000000000000000 bfe345f01cce37bb 0000000000000000 bfe345f01cce37bb 0000000000000000 1 # x=-0x1.6000000000000p-1 y=0x0.0p+0
+negative_second_interval_above bfe6000000000001 0000000000000000 bfe345f01cce37bc 0000000000000000 bfe345f01cce37bc 0000000000000000 1 # x=-0x1.6000000000001p-1 y=0x0.0p+0
+third_interval_below 3ff2ffffffffffff 0000000000000000 3febde70ed439fe6 0000000000000000 3febde70ed439fe6 0000000000000000 1 # x=0x1.2ffffffffffffp+0 y=0x0.0p+0
+third_interval_at 3ff3000000000000 0000000000000000 3febde70ed439fe7 0000000000000000 3febde70ed439fe7 0000000000000000 1 # x=0x1.3000000000000p+0 y=0x0.0p+0
+third_interval_above 3ff3000000000001 0000000000000000 3febde70ed439fe8 0000000000000000 3febde70ed439fe8 0000000000000000 1 # x=0x1.3000000000001p+0 y=0x0.0p+0
+negative_third_interval_below bff2ffffffffffff 0000000000000000 bfebde70ed439fe6 0000000000000000 bfebde70ed439fe6 0000000000000000 1 # x=-0x1.2ffffffffffffp+0 y=0x0.0p+0
+negative_third_interval_at bff3000000000000 0000000000000000 bfebde70ed439fe7 0000000000000000 bfebde70ed439fe7 0000000000000000 1 # x=-0x1.3000000000000p+0 y=0x0.0p+0
+negative_third_interval_above bff3000000000001 0000000000000000 bfebde70ed439fe8 0000000000000000 bfebde70ed439fe8 0000000000000000 1 # x=-0x1.3000000000001p+0 y=0x0.0p+0
+reciprocal_interval_below 40037fffffffffff 0000000000000000 3ff2e75728833a54 0000000000000000 3ff2e75728833a54 0000000000000000 1 # x=0x1.37fffffffffffp+1 y=0x0.0p+0
+reciprocal_interval_at 4003800000000000 0000000000000000 3ff2e75728833a54 0000000000000000 3ff2e75728833a54 0000000000000000 1 # x=0x1.3800000000000p+1 y=0x0.0p+0
+reciprocal_interval_above 4003800000000001 0000000000000000 3ff2e75728833a54 0000000000000000 3ff2e75728833a54 0000000000000000 1 # x=0x1.3800000000001p+1 y=0x0.0p+0
+negative_reciprocal_interval_below c0037fffffffffff 0000000000000000 bff2e75728833a54 0000000000000000 bff2e75728833a54 0000000000000000 1 # x=-0x1.37fffffffffffp+1 y=0x0.0p+0
+negative_reciprocal_interval_at c003800000000000 0000000000000000 bff2e75728833a54 0000000000000000 bff2e75728833a54 0000000000000000 1 # x=-0x1.3800000000000p+1 y=0x0.0p+0
+negative_reciprocal_interval_above c003800000000001 0000000000000000 bff2e75728833a54 0000000000000000 bff2e75728833a54 0000000000000000 1 # x=-0x1.3800000000001p+1 y=0x0.0p+0
+asymptote_below 440fffffffffffff 0000000000000000 3ff921fb54442d18 0000000000000000 3ff921fb54442d18 0000000000000000 1 # x=0x1.fffffffffffffp+65 y=0x0.0p+0
+asymptote_at 4410000000000000 0000000000000000 3ff921fb54442d18 0000000000000000 3ff921fb54442d18 0000000000000000 1 # x=0x1.0000000000000p+66 y=0x0.0p+0
+asymptote_above 4410000000000001 0000000000000000 3ff921fb54442d18 0000000000000000 3ff921fb54442d18 0000000000000000 1 # x=0x1.0000000000001p+66 y=0x0.0p+0
+negative_asymptote_below c40fffffffffffff 0000000000000000 bff921fb54442d18 0000000000000000 bff921fb54442d18 0000000000000000 1 # x=-0x1.fffffffffffffp+65 y=0x0.0p+0
+negative_asymptote_at c410000000000000 0000000000000000 bff921fb54442d18 0000000000000000 bff921fb54442d18 0000000000000000 1 # x=-0x1.0000000000000p+66 y=0x0.0p+0
+negative_asymptote_above c410000000000001 0000000000000000 bff921fb54442d18 0000000000000000 bff921fb54442d18 0000000000000000 1 # x=-0x1.0000000000001p+66 y=0x0.0p+0

+ 66 - 0
tests/dmath/cases/atan2.txt

@@ -0,0 +1,66 @@
+# dmath_atan2
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep 8036728548f8a013
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+quadrant_1 4017400000000000 3fcc000000000000 3ff887e768182da0 0000000000000000 3ff887e768182da0 0000000000000000 2 # x=0x1.7400000000000p+2 y=0x1.c000000000000p-3
+quadrant_2 4017400000000000 bfcc000000000000 3ff9bc0f40702c91 0000000000000000 3ff9bc0f40702c91 0000000000000000 2 # x=0x1.7400000000000p+2 y=-0x1.c000000000000p-3
+quadrant_3 c017400000000000 3fcc000000000000 bff887e768182da0 0000000000000000 bff887e768182da0 0000000000000000 2 # x=-0x1.7400000000000p+2 y=0x1.c000000000000p-3
+quadrant_4 c017400000000000 bfcc000000000000 bff9bc0f40702c91 0000000000000000 bff9bc0f40702c91 0000000000000000 2 # x=-0x1.7400000000000p+2 y=-0x1.c000000000000p-3
+axes_0000000000000000_0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 2 # x=0x0.0p+0 y=0x0.0p+0
+axes_0000000000000000_8000000000000000 0000000000000000 8000000000000000 400921fb54442d18 0000000000000000 400921fb54442d18 0000000000000000 2 # x=0x0.0p+0 y=-0x0.0p+0
+axes_0000000000000000_7ff0000000000000 0000000000000000 7ff0000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 2 # x=0x0.0p+0 y=inf
+axes_0000000000000000_fff0000000000000 0000000000000000 fff0000000000000 400921fb54442d18 0000000000000000 400921fb54442d18 0000000000000000 2 # x=0x0.0p+0 y=-inf
+axes_8000000000000000_0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 2 # x=-0x0.0p+0 y=0x0.0p+0
+axes_8000000000000000_8000000000000000 8000000000000000 8000000000000000 c00921fb54442d18 0000000000000000 c00921fb54442d18 0000000000000000 2 # x=-0x0.0p+0 y=-0x0.0p+0
+axes_8000000000000000_7ff0000000000000 8000000000000000 7ff0000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 2 # x=-0x0.0p+0 y=inf
+axes_8000000000000000_fff0000000000000 8000000000000000 fff0000000000000 c00921fb54442d18 0000000000000000 c00921fb54442d18 0000000000000000 2 # x=-0x0.0p+0 y=-inf
+axes_7ff0000000000000_0000000000000000 7ff0000000000000 0000000000000000 3ff921fb54442d18 0000000000000000 3ff921fb54442d18 0000000000000000 2 # x=inf y=0x0.0p+0
+axes_7ff0000000000000_8000000000000000 7ff0000000000000 8000000000000000 3ff921fb54442d18 0000000000000000 3ff921fb54442d18 0000000000000000 2 # x=inf y=-0x0.0p+0
+axes_7ff0000000000000_7ff0000000000000 7ff0000000000000 7ff0000000000000 3fe921fb54442d18 0000000000000000 3fe921fb54442d18 0000000000000000 2 # x=inf y=inf
+axes_7ff0000000000000_fff0000000000000 7ff0000000000000 fff0000000000000 4002d97c7f3321d2 0000000000000000 4002d97c7f3321d2 0000000000000000 2 # x=inf y=-inf
+axes_fff0000000000000_0000000000000000 fff0000000000000 0000000000000000 bff921fb54442d18 0000000000000000 bff921fb54442d18 0000000000000000 2 # x=-inf y=0x0.0p+0
+axes_fff0000000000000_8000000000000000 fff0000000000000 8000000000000000 bff921fb54442d18 0000000000000000 bff921fb54442d18 0000000000000000 2 # x=-inf y=-0x0.0p+0
+axes_fff0000000000000_7ff0000000000000 fff0000000000000 7ff0000000000000 bfe921fb54442d18 0000000000000000 bfe921fb54442d18 0000000000000000 2 # x=-inf y=inf
+axes_fff0000000000000_fff0000000000000 fff0000000000000 fff0000000000000 c002d97c7f3321d2 0000000000000000 c002d97c7f3321d2 0000000000000000 2 # x=-inf y=-inf
+positive_zero_ordinate 0000000000000000 c017400000000000 400921fb54442d18 0000000000000000 400921fb54442d18 0000000000000000 2 # x=0x0.0p+0 y=-0x1.7400000000000p+2
+positive_zero_abscissa c017400000000000 0000000000000000 bff921fb54442d18 0000000000000000 bff921fb54442d18 0000000000000000 2 # x=-0x1.7400000000000p+2 y=0x0.0p+0
+negative_zero_ordinate 8000000000000000 c017400000000000 c00921fb54442d18 0000000000000000 c00921fb54442d18 0000000000000000 2 # x=-0x0.0p+0 y=-0x1.7400000000000p+2
+negative_zero_abscissa c017400000000000 8000000000000000 bff921fb54442d18 0000000000000000 bff921fb54442d18 0000000000000000 2 # x=-0x1.7400000000000p+2 y=-0x0.0p+0
+least_subnormal_ordinate 0000000000000001 c017400000000000 400921fb54442d18 0000000000000000 400921fb54442d18 0000000000000000 2 # x=0x0.0000000000001p-1022 y=-0x1.7400000000000p+2
+least_subnormal_abscissa c017400000000000 0000000000000001 bff921fb54442d18 0000000000000000 bff921fb54442d18 0000000000000000 2 # x=-0x1.7400000000000p+2 y=0x0.0000000000001p-1022
+negative_least_subnormal_ordinate 8000000000000001 c017400000000000 c00921fb54442d18 0000000000000000 c00921fb54442d18 0000000000000000 2 # x=-0x0.0000000000001p-1022 y=-0x1.7400000000000p+2
+negative_least_subnormal_abscissa c017400000000000 8000000000000001 bff921fb54442d18 0000000000000000 bff921fb54442d18 0000000000000000 2 # x=-0x1.7400000000000p+2 y=-0x0.0000000000001p-1022
+third_subnormal_ordinate 0000000000000003 c017400000000000 400921fb54442d18 0000000000000000 400921fb54442d18 0000000000000000 2 # x=0x0.0000000000003p-1022 y=-0x1.7400000000000p+2
+third_subnormal_abscissa c017400000000000 0000000000000003 bff921fb54442d18 0000000000000000 bff921fb54442d18 0000000000000000 2 # x=-0x1.7400000000000p+2 y=0x0.0000000000003p-1022
+negative_third_subnormal_ordinate 8000000000000003 c017400000000000 c00921fb54442d18 0000000000000000 c00921fb54442d18 0000000000000000 2 # x=-0x0.0000000000003p-1022 y=-0x1.7400000000000p+2
+negative_third_subnormal_abscissa c017400000000000 8000000000000003 bff921fb54442d18 0000000000000000 bff921fb54442d18 0000000000000000 2 # x=-0x1.7400000000000p+2 y=-0x0.0000000000003p-1022
+largest_subnormal_ordinate 000fffffffffffff c017400000000000 400921fb54442d18 0000000000000000 400921fb54442d18 0000000000000000 2 # x=0x0.fffffffffffffp-1022 y=-0x1.7400000000000p+2
+largest_subnormal_abscissa c017400000000000 000fffffffffffff bff921fb54442d18 0000000000000000 bff921fb54442d18 0000000000000000 2 # x=-0x1.7400000000000p+2 y=0x0.fffffffffffffp-1022
+negative_largest_subnormal_ordinate 800fffffffffffff c017400000000000 c00921fb54442d18 0000000000000000 c00921fb54442d18 0000000000000000 2 # x=-0x0.fffffffffffffp-1022 y=-0x1.7400000000000p+2
+negative_largest_subnormal_abscissa c017400000000000 800fffffffffffff bff921fb54442d18 0000000000000000 bff921fb54442d18 0000000000000000 2 # x=-0x1.7400000000000p+2 y=-0x0.fffffffffffffp-1022
+least_normal_ordinate 0010000000000000 c017400000000000 400921fb54442d18 0000000000000000 400921fb54442d18 0000000000000000 2 # x=0x1.0000000000000p-1022 y=-0x1.7400000000000p+2
+least_normal_abscissa c017400000000000 0010000000000000 bff921fb54442d18 0000000000000000 bff921fb54442d18 0000000000000000 2 # x=-0x1.7400000000000p+2 y=0x1.0000000000000p-1022
+negative_least_normal_ordinate 8010000000000000 c017400000000000 c00921fb54442d18 0000000000000000 c00921fb54442d18 0000000000000000 2 # x=-0x1.0000000000000p-1022 y=-0x1.7400000000000p+2
+negative_least_normal_abscissa c017400000000000 8010000000000000 bff921fb54442d18 0000000000000000 bff921fb54442d18 0000000000000000 2 # x=-0x1.7400000000000p+2 y=-0x1.0000000000000p-1022
+largest_finite_ordinate 7fefffffffffffff c017400000000000 3ff921fb54442d18 0000000000000000 3ff921fb54442d18 0000000000000000 2 # x=0x1.fffffffffffffp+1023 y=-0x1.7400000000000p+2
+largest_finite_abscissa c017400000000000 7fefffffffffffff 8017400000000001 0000000000000000 8017400000000001 0000000000000000 2 # x=-0x1.7400000000000p+2 y=0x1.fffffffffffffp+1023
+negative_largest_finite_ordinate ffefffffffffffff c017400000000000 bff921fb54442d18 0000000000000000 bff921fb54442d18 0000000000000000 2 # x=-0x1.fffffffffffffp+1023 y=-0x1.7400000000000p+2
+negative_largest_finite_abscissa c017400000000000 ffefffffffffffff c00921fb54442d18 0000000000000000 c00921fb54442d18 0000000000000000 2 # x=-0x1.7400000000000p+2 y=-0x1.fffffffffffffp+1023
+positive_infinity_ordinate 7ff0000000000000 c017400000000000 3ff921fb54442d18 0000000000000000 3ff921fb54442d18 0000000000000000 2 # x=inf y=-0x1.7400000000000p+2
+positive_infinity_abscissa c017400000000000 7ff0000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 2 # x=-0x1.7400000000000p+2 y=inf
+negative_infinity_ordinate fff0000000000000 c017400000000000 bff921fb54442d18 0000000000000000 bff921fb54442d18 0000000000000000 2 # x=-inf y=-0x1.7400000000000p+2
+negative_infinity_abscissa c017400000000000 fff0000000000000 c00921fb54442d18 0000000000000000 c00921fb54442d18 0000000000000000 2 # x=-0x1.7400000000000p+2 y=-inf
+quiet_nan_payload_ordinate 7ff8abcdef135790 c017400000000000 nan 0000000000000000 nan 0000000000000000 2 # x=nan y=-0x1.7400000000000p+2
+quiet_nan_payload_abscissa c017400000000000 7ff8abcdef135790 nan 0000000000000000 nan 0000000000000000 2 # x=-0x1.7400000000000p+2 y=nan
+negative_quiet_nan_payload_ordinate fff8abcdef135790 c017400000000000 nan 0000000000000000 nan 0000000000000000 2 # x=nan y=-0x1.7400000000000p+2
+negative_quiet_nan_payload_abscissa c017400000000000 fff8abcdef135790 nan 0000000000000000 nan 0000000000000000 2 # x=-0x1.7400000000000p+2 y=nan
+signaling_nan_payload_ordinate 7ff0000000010248 c017400000000000 nan 0000000000000000 nan 0000000000000000 2 # x=nan y=-0x1.7400000000000p+2
+signaling_nan_payload_abscissa c017400000000000 7ff0000000010248 nan 0000000000000000 nan 0000000000000000 2 # x=-0x1.7400000000000p+2 y=nan
+negative_signaling_nan_payload_ordinate fff0000000010248 c017400000000000 nan 0000000000000000 nan 0000000000000000 2 # x=nan y=-0x1.7400000000000p+2
+negative_signaling_nan_payload_abscissa c017400000000000 fff0000000010248 nan 0000000000000000 nan 0000000000000000 2 # x=-0x1.7400000000000p+2 y=nan
+tiny_ratio 0170000000000000 7830000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 2 # x=0x1.0000000000000p-1000 y=0x1.0000000000000p+900
+huge_ratio 7830000000000000 0170000000000000 3ff921fb54442d18 0000000000000000 3ff921fb54442d18 0000000000000000 2 # x=0x1.0000000000000p+900 y=0x1.0000000000000p-1000
+tiny_ratio_negative_x 0170000000000000 f830000000000000 400921fb54442d18 0000000000000000 400921fb54442d18 0000000000000000 2 # x=0x1.0000000000000p-1000 y=-0x1.0000000000000p+900
+unit_abscissa_shortcut 3ffd000000000000 3ff0000000000000 3ff110eb007f39f7 0000000000000000 3ff110eb007f39f7 0000000000000000 2 # x=0x1.d000000000000p+0 y=0x1.0000000000000p+0

+ 46 - 0
tests/dmath/cases/cbrt.txt

@@ -0,0 +1,46 @@
+# dmath_cbrt
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep 729d75e71202e9b4
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+positive_zero 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 1 # x=0x0.0p+0 y=0x0.0p+0
+negative_zero 8000000000000000 0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 1 # x=-0x0.0p+0 y=0x0.0p+0
+least_subnormal 0000000000000001 0000000000000000 2990000000000000 0000000000000000 2990000000000000 0000000000000000 1 # x=0x0.0000000000001p-1022 y=0x0.0p+0
+negative_least_subnormal 8000000000000001 0000000000000000 a990000000000000 0000000000000000 a990000000000000 0000000000000000 1 # x=-0x0.0000000000001p-1022 y=0x0.0p+0
+third_subnormal 0000000000000003 0000000000000000 2997137449123ef6 0000000000000000 2997137449123ef6 0000000000000000 1 # x=0x0.0000000000003p-1022 y=0x0.0p+0
+negative_third_subnormal 8000000000000003 0000000000000000 a997137449123ef6 0000000000000000 a997137449123ef6 0000000000000000 1 # x=-0x0.0000000000003p-1022 y=0x0.0p+0
+largest_subnormal 000fffffffffffff 0000000000000000 2aa428a2f98d728a 0000000000000000 2aa428a2f98d728a 0000000000000000 1 # x=0x0.fffffffffffffp-1022 y=0x0.0p+0
+negative_largest_subnormal 800fffffffffffff 0000000000000000 aaa428a2f98d728a 0000000000000000 aaa428a2f98d728a 0000000000000000 1 # x=-0x0.fffffffffffffp-1022 y=0x0.0p+0
+least_normal 0010000000000000 0000000000000000 2aa428a2f98d728b 0000000000000000 2aa428a2f98d728b 0000000000000000 1 # x=0x1.0000000000000p-1022 y=0x0.0p+0
+negative_least_normal 8010000000000000 0000000000000000 aaa428a2f98d728b 0000000000000000 aaa428a2f98d728b 0000000000000000 1 # x=-0x1.0000000000000p-1022 y=0x0.0p+0
+largest_finite 7fefffffffffffff 0000000000000000 554428a2f98d728b 0000000000000000 554428a2f98d728b 0000000000000000 1 # x=0x1.fffffffffffffp+1023 y=0x0.0p+0
+negative_largest_finite ffefffffffffffff 0000000000000000 d54428a2f98d728b 0000000000000000 d54428a2f98d728b 0000000000000000 1 # x=-0x1.fffffffffffffp+1023 y=0x0.0p+0
+positive_infinity 7ff0000000000000 0000000000000000 +inf 0000000000000000 +inf 0000000000000000 1 # x=inf y=0x0.0p+0
+negative_infinity fff0000000000000 0000000000000000 -inf 0000000000000000 -inf 0000000000000000 1 # x=-inf y=0x0.0p+0
+quiet_nan_payload 7ff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+negative_quiet_nan_payload fff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+signaling_nan_payload 7ff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+negative_signaling_nan_payload fff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+exact_positive_cube 4063693000000000 0000000000000000 4015800000000000 0000000000000000 4015800000000000 0000000000000000 1 # x=0x1.3693000000000p+7 y=0x0.0p+0
+exact_negative_cube c063693000000000 0000000000000000 c015800000000000 0000000000000000 c015800000000000 0000000000000000 1 # x=-0x1.3693000000000p+7 y=0x0.0p+0
+irrational_positive 4033600000000000 0000000000000000 40057c9b15ef8f92 0000000000000000 40057c9b15ef8f92 0000000000000000 1 # x=0x1.3600000000000p+4 y=0x0.0p+0
+irrational_negative c033600000000000 0000000000000000 c0057c9b15ef8f92 0000000000000000 c0057c9b15ef8f92 0000000000000000 1 # x=-0x1.3600000000000p+4 y=0x0.0p+0
+exponent_class_0_below 65772fffffffffff 0000000000000000 4c721b3acf1ef541 0000000000000000 4c721b3acf1ef541 0000000000000000 1 # x=0x1.72fffffffffffp+600 y=0x0.0p+0
+exponent_class_0_at 6577300000000000 0000000000000000 4c721b3acf1ef541 0000000000000000 4c721b3acf1ef542 0000000000000000 1 # x=0x1.7300000000000p+600 y=0x0.0p+0
+exponent_class_0_above 6577300000000001 0000000000000000 4c721b3acf1ef542 0000000000000000 4c721b3acf1ef542 0000000000000000 1 # x=0x1.7300000000001p+600 y=0x0.0p+0
+negative_exponent_class_0_below e5772fffffffffff 0000000000000000 cc721b3acf1ef541 0000000000000000 cc721b3acf1ef541 0000000000000000 1 # x=-0x1.72fffffffffffp+600 y=0x0.0p+0
+negative_exponent_class_0_at e577300000000000 0000000000000000 cc721b3acf1ef541 0000000000000000 cc721b3acf1ef542 0000000000000000 1 # x=-0x1.7300000000000p+600 y=0x0.0p+0
+negative_exponent_class_0_above e577300000000001 0000000000000000 cc721b3acf1ef542 0000000000000000 cc721b3acf1ef542 0000000000000000 1 # x=-0x1.7300000000001p+600 y=0x0.0p+0
+exponent_class_1_below 65872fffffffffff 0000000000000000 4c76d0060407c5dd 0000000000000000 4c76d0060407c5dd 0000000000000000 1 # x=0x1.72fffffffffffp+601 y=0x0.0p+0
+exponent_class_1_at 6587300000000000 0000000000000000 4c76d0060407c5dd 0000000000000000 4c76d0060407c5dd 0000000000000000 1 # x=0x1.7300000000000p+601 y=0x0.0p+0
+exponent_class_1_above 6587300000000001 0000000000000000 4c76d0060407c5de 0000000000000000 4c76d0060407c5de 0000000000000000 1 # x=0x1.7300000000001p+601 y=0x0.0p+0
+negative_exponent_class_1_below e5872fffffffffff 0000000000000000 cc76d0060407c5dd 0000000000000000 cc76d0060407c5dd 0000000000000000 1 # x=-0x1.72fffffffffffp+601 y=0x0.0p+0
+negative_exponent_class_1_at e587300000000000 0000000000000000 cc76d0060407c5dd 0000000000000000 cc76d0060407c5dd 0000000000000000 1 # x=-0x1.7300000000000p+601 y=0x0.0p+0
+negative_exponent_class_1_above e587300000000001 0000000000000000 cc76d0060407c5de 0000000000000000 cc76d0060407c5de 0000000000000000 1 # x=-0x1.7300000000001p+601 y=0x0.0p+0
+exponent_class_2_below 65972fffffffffff 0000000000000000 4c7cbdf7f21fbdb5 0000000000000000 4c7cbdf7f21fbdb5 0000000000000000 1 # x=0x1.72fffffffffffp+602 y=0x0.0p+0
+exponent_class_2_at 6597300000000000 0000000000000000 4c7cbdf7f21fbdb6 0000000000000000 4c7cbdf7f21fbdb6 0000000000000000 1 # x=0x1.7300000000000p+602 y=0x0.0p+0
+exponent_class_2_above 6597300000000001 0000000000000000 4c7cbdf7f21fbdb6 0000000000000000 4c7cbdf7f21fbdb6 0000000000000000 1 # x=0x1.7300000000001p+602 y=0x0.0p+0
+negative_exponent_class_2_below e5972fffffffffff 0000000000000000 cc7cbdf7f21fbdb5 0000000000000000 cc7cbdf7f21fbdb5 0000000000000000 1 # x=-0x1.72fffffffffffp+602 y=0x0.0p+0
+negative_exponent_class_2_at e597300000000000 0000000000000000 cc7cbdf7f21fbdb6 0000000000000000 cc7cbdf7f21fbdb6 0000000000000000 1 # x=-0x1.7300000000000p+602 y=0x0.0p+0
+negative_exponent_class_2_above e597300000000001 0000000000000000 cc7cbdf7f21fbdb6 0000000000000000 cc7cbdf7f21fbdb6 0000000000000000 1 # x=-0x1.7300000000001p+602 y=0x0.0p+0

+ 68 - 0
tests/dmath/cases/ceil.txt

@@ -0,0 +1,68 @@
+# dmath_ceil
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep d12c5e7c92c367d5
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+positive_zero 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.0p+0 y=0x0.0p+0
+negative_zero 8000000000000000 0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x0.0p+0 y=0x0.0p+0
+least_subnormal 0000000000000001 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 0 # x=0x0.0000000000001p-1022 y=0x0.0p+0
+negative_least_subnormal 8000000000000001 0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x0.0000000000001p-1022 y=0x0.0p+0
+third_subnormal 0000000000000003 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 0 # x=0x0.0000000000003p-1022 y=0x0.0p+0
+negative_third_subnormal 8000000000000003 0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x0.0000000000003p-1022 y=0x0.0p+0
+largest_subnormal 000fffffffffffff 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 0 # x=0x0.fffffffffffffp-1022 y=0x0.0p+0
+negative_largest_subnormal 800fffffffffffff 0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x0.fffffffffffffp-1022 y=0x0.0p+0
+least_normal 0010000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 0 # x=0x1.0000000000000p-1022 y=0x0.0p+0
+negative_least_normal 8010000000000000 0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x1.0000000000000p-1022 y=0x0.0p+0
+largest_finite 7fefffffffffffff 0000000000000000 7fefffffffffffff 0000000000000000 7fefffffffffffff 0000000000000000 0 # x=0x1.fffffffffffffp+1023 y=0x0.0p+0
+negative_largest_finite ffefffffffffffff 0000000000000000 ffefffffffffffff 0000000000000000 ffefffffffffffff 0000000000000000 0 # x=-0x1.fffffffffffffp+1023 y=0x0.0p+0
+positive_infinity 7ff0000000000000 0000000000000000 +inf 0000000000000000 +inf 0000000000000000 0 # x=inf y=0x0.0p+0
+negative_infinity fff0000000000000 0000000000000000 -inf 0000000000000000 -inf 0000000000000000 0 # x=-inf y=0x0.0p+0
+quiet_nan_payload 7ff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=0x0.0p+0
+negative_quiet_nan_payload fff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=0x0.0p+0
+signaling_nan_payload 7ff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=0x0.0p+0
+negative_signaling_nan_payload fff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=0x0.0p+0
+unit_below 3fefffffffffffff 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 0 # x=0x1.fffffffffffffp-1 y=0x0.0p+0
+unit_at 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 0 # x=0x1.0000000000000p+0 y=0x0.0p+0
+unit_above 3ff0000000000001 0000000000000000 4000000000000000 0000000000000000 4000000000000000 0000000000000000 0 # x=0x1.0000000000001p+0 y=0x0.0p+0
+negative_unit_below bfefffffffffffff 0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x1.fffffffffffffp-1 y=0x0.0p+0
+negative_unit_at bff0000000000000 0000000000000000 bff0000000000000 0000000000000000 bff0000000000000 0000000000000000 0 # x=-0x1.0000000000000p+0 y=0x0.0p+0
+negative_unit_above bff0000000000001 0000000000000000 bff0000000000000 0000000000000000 bff0000000000000 0000000000000000 0 # x=-0x1.0000000000001p+0 y=0x0.0p+0
+half_below 3fdfffffffffffff 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 0 # x=0x1.fffffffffffffp-2 y=0x0.0p+0
+half_at 3fe0000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 0 # x=0x1.0000000000000p-1 y=0x0.0p+0
+half_above 3fe0000000000001 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 0 # x=0x1.0000000000001p-1 y=0x0.0p+0
+negative_half_below bfdfffffffffffff 0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x1.fffffffffffffp-2 y=0x0.0p+0
+negative_half_at bfe0000000000000 0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x1.0000000000000p-1 y=0x0.0p+0
+negative_half_above bfe0000000000001 0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x1.0000000000001p-1 y=0x0.0p+0
+word_split_below 412fffffffffffff 0000000000000000 4130000000000000 0000000000000000 4130000000000000 0000000000000000 0 # x=0x1.fffffffffffffp+19 y=0x0.0p+0
+word_split_at 4130000000000000 0000000000000000 4130000000000000 0000000000000000 4130000000000000 0000000000000000 0 # x=0x1.0000000000000p+20 y=0x0.0p+0
+word_split_above 4130000000000001 0000000000000000 4130000100000000 0000000000000000 4130000100000000 0000000000000000 0 # x=0x1.0000000000001p+20 y=0x0.0p+0
+negative_word_split_below c12fffffffffffff 0000000000000000 c12ffffe00000000 0000000000000000 c12ffffe00000000 0000000000000000 0 # x=-0x1.fffffffffffffp+19 y=0x0.0p+0
+negative_word_split_at c130000000000000 0000000000000000 c130000000000000 0000000000000000 c130000000000000 0000000000000000 0 # x=-0x1.0000000000000p+20 y=0x0.0p+0
+negative_word_split_above c130000000000001 0000000000000000 c130000000000000 0000000000000000 c130000000000000 0000000000000000 0 # x=-0x1.0000000000001p+20 y=0x0.0p+0
+signed32_below 41dfffffffffffff 0000000000000000 41e0000000000000 0000000000000000 41e0000000000000 0000000000000000 0 # x=0x1.fffffffffffffp+30 y=0x0.0p+0
+signed32_at 41e0000000000000 0000000000000000 41e0000000000000 0000000000000000 41e0000000000000 0000000000000000 0 # x=0x1.0000000000000p+31 y=0x0.0p+0
+signed32_above 41e0000000000001 0000000000000000 41e0000000200000 0000000000000000 41e0000000200000 0000000000000000 0 # x=0x1.0000000000001p+31 y=0x0.0p+0
+negative_signed32_below c1dfffffffffffff 0000000000000000 c1dfffffffc00000 0000000000000000 c1dfffffffc00000 0000000000000000 0 # x=-0x1.fffffffffffffp+30 y=0x0.0p+0
+negative_signed32_at c1e0000000000000 0000000000000000 c1e0000000000000 0000000000000000 c1e0000000000000 0000000000000000 0 # x=-0x1.0000000000000p+31 y=0x0.0p+0
+negative_signed32_above c1e0000000000001 0000000000000000 c1e0000000000000 0000000000000000 c1e0000000000000 0000000000000000 0 # x=-0x1.0000000000001p+31 y=0x0.0p+0
+last_fractional_binade_below 431fffffffffffff 0000000000000000 4320000000000000 0000000000000000 4320000000000000 0000000000000000 0 # x=0x1.fffffffffffffp+50 y=0x0.0p+0
+last_fractional_binade_at 4320000000000000 0000000000000000 4320000000000000 0000000000000000 4320000000000000 0000000000000000 0 # x=0x1.0000000000000p+51 y=0x0.0p+0
+last_fractional_binade_above 4320000000000001 0000000000000000 4320000000000002 0000000000000000 4320000000000002 0000000000000000 0 # x=0x1.0000000000001p+51 y=0x0.0p+0
+negative_last_fractional_binade_below c31fffffffffffff 0000000000000000 c31ffffffffffffc 0000000000000000 c31ffffffffffffc 0000000000000000 0 # x=-0x1.fffffffffffffp+50 y=0x0.0p+0
+negative_last_fractional_binade_at c320000000000000 0000000000000000 c320000000000000 0000000000000000 c320000000000000 0000000000000000 0 # x=-0x1.0000000000000p+51 y=0x0.0p+0
+negative_last_fractional_binade_above c320000000000001 0000000000000000 c320000000000000 0000000000000000 c320000000000000 0000000000000000 0 # x=-0x1.0000000000001p+51 y=0x0.0p+0
+integral_binade_below 432fffffffffffff 0000000000000000 4330000000000000 0000000000000000 4330000000000000 0000000000000000 0 # x=0x1.fffffffffffffp+51 y=0x0.0p+0
+integral_binade_at 4330000000000000 0000000000000000 4330000000000000 0000000000000000 4330000000000000 0000000000000000 0 # x=0x1.0000000000000p+52 y=0x0.0p+0
+integral_binade_above 4330000000000001 0000000000000000 4330000000000001 0000000000000000 4330000000000001 0000000000000000 0 # x=0x1.0000000000001p+52 y=0x0.0p+0
+negative_integral_binade_below c32fffffffffffff 0000000000000000 c32ffffffffffffe 0000000000000000 c32ffffffffffffe 0000000000000000 0 # x=-0x1.fffffffffffffp+51 y=0x0.0p+0
+negative_integral_binade_at c330000000000000 0000000000000000 c330000000000000 0000000000000000 c330000000000000 0000000000000000 0 # x=-0x1.0000000000000p+52 y=0x0.0p+0
+negative_integral_binade_above c330000000000001 0000000000000000 c330000000000001 0000000000000000 c330000000000001 0000000000000000 0 # x=-0x1.0000000000001p+52 y=0x0.0p+0
+signed64_below 43dfffffffffffff 0000000000000000 43dfffffffffffff 0000000000000000 43dfffffffffffff 0000000000000000 0 # x=0x1.fffffffffffffp+62 y=0x0.0p+0
+signed64_at 43e0000000000000 0000000000000000 43e0000000000000 0000000000000000 43e0000000000000 0000000000000000 0 # x=0x1.0000000000000p+63 y=0x0.0p+0
+signed64_above 43e0000000000001 0000000000000000 43e0000000000001 0000000000000000 43e0000000000001 0000000000000000 0 # x=0x1.0000000000001p+63 y=0x0.0p+0
+negative_signed64_below c3dfffffffffffff 0000000000000000 c3dfffffffffffff 0000000000000000 c3dfffffffffffff 0000000000000000 0 # x=-0x1.fffffffffffffp+62 y=0x0.0p+0
+negative_signed64_at c3e0000000000000 0000000000000000 c3e0000000000000 0000000000000000 c3e0000000000000 0000000000000000 0 # x=-0x1.0000000000000p+63 y=0x0.0p+0
+negative_signed64_above c3e0000000000001 0000000000000000 c3e0000000000001 0000000000000000 c3e0000000000001 0000000000000000 0 # x=-0x1.0000000000001p+63 y=0x0.0p+0
+up_from_positive_fraction 4037100000000000 0000000000000000 4038000000000000 0000000000000000 4038000000000000 0000000000000000 0 # x=0x1.7100000000000p+4 y=0x0.0p+0
+up_from_negative_fraction c037100000000000 0000000000000000 c037000000000000 0000000000000000 c037000000000000 0000000000000000 0 # x=-0x1.7100000000000p+4 y=0x0.0p+0

+ 47 - 0
tests/dmath/cases/copysign.txt

@@ -0,0 +1,47 @@
+# dmath_copysign
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep 4a74d6be7e486ed6
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+positive_zero_positive_sign 0000000000000000 3ae0000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.0p+0 y=0x1.0000000000000p-81
+positive_zero_negative_sign 0000000000000000 c500000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=0x0.0p+0 y=-0x1.0000000000000p+81
+negative_zero_positive_sign 8000000000000000 3ae0000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=-0x0.0p+0 y=0x1.0000000000000p-81
+negative_zero_negative_sign 8000000000000000 c500000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x0.0p+0 y=-0x1.0000000000000p+81
+least_subnormal_positive_sign 0000000000000001 3ae0000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=0x0.0000000000001p-1022 y=0x1.0000000000000p-81
+least_subnormal_negative_sign 0000000000000001 c500000000000000 8000000000000001 0000000000000000 8000000000000001 0000000000000000 0 # x=0x0.0000000000001p-1022 y=-0x1.0000000000000p+81
+negative_least_subnormal_positive_sign 8000000000000001 3ae0000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=-0x0.0000000000001p-1022 y=0x1.0000000000000p-81
+negative_least_subnormal_negative_sign 8000000000000001 c500000000000000 8000000000000001 0000000000000000 8000000000000001 0000000000000000 0 # x=-0x0.0000000000001p-1022 y=-0x1.0000000000000p+81
+third_subnormal_positive_sign 0000000000000003 3ae0000000000000 0000000000000003 0000000000000000 0000000000000003 0000000000000000 0 # x=0x0.0000000000003p-1022 y=0x1.0000000000000p-81
+third_subnormal_negative_sign 0000000000000003 c500000000000000 8000000000000003 0000000000000000 8000000000000003 0000000000000000 0 # x=0x0.0000000000003p-1022 y=-0x1.0000000000000p+81
+negative_third_subnormal_positive_sign 8000000000000003 3ae0000000000000 0000000000000003 0000000000000000 0000000000000003 0000000000000000 0 # x=-0x0.0000000000003p-1022 y=0x1.0000000000000p-81
+negative_third_subnormal_negative_sign 8000000000000003 c500000000000000 8000000000000003 0000000000000000 8000000000000003 0000000000000000 0 # x=-0x0.0000000000003p-1022 y=-0x1.0000000000000p+81
+largest_subnormal_positive_sign 000fffffffffffff 3ae0000000000000 000fffffffffffff 0000000000000000 000fffffffffffff 0000000000000000 0 # x=0x0.fffffffffffffp-1022 y=0x1.0000000000000p-81
+largest_subnormal_negative_sign 000fffffffffffff c500000000000000 800fffffffffffff 0000000000000000 800fffffffffffff 0000000000000000 0 # x=0x0.fffffffffffffp-1022 y=-0x1.0000000000000p+81
+negative_largest_subnormal_positive_sign 800fffffffffffff 3ae0000000000000 000fffffffffffff 0000000000000000 000fffffffffffff 0000000000000000 0 # x=-0x0.fffffffffffffp-1022 y=0x1.0000000000000p-81
+negative_largest_subnormal_negative_sign 800fffffffffffff c500000000000000 800fffffffffffff 0000000000000000 800fffffffffffff 0000000000000000 0 # x=-0x0.fffffffffffffp-1022 y=-0x1.0000000000000p+81
+least_normal_positive_sign 0010000000000000 3ae0000000000000 0010000000000000 0000000000000000 0010000000000000 0000000000000000 0 # x=0x1.0000000000000p-1022 y=0x1.0000000000000p-81
+least_normal_negative_sign 0010000000000000 c500000000000000 8010000000000000 0000000000000000 8010000000000000 0000000000000000 0 # x=0x1.0000000000000p-1022 y=-0x1.0000000000000p+81
+negative_least_normal_positive_sign 8010000000000000 3ae0000000000000 0010000000000000 0000000000000000 0010000000000000 0000000000000000 0 # x=-0x1.0000000000000p-1022 y=0x1.0000000000000p-81
+negative_least_normal_negative_sign 8010000000000000 c500000000000000 8010000000000000 0000000000000000 8010000000000000 0000000000000000 0 # x=-0x1.0000000000000p-1022 y=-0x1.0000000000000p+81
+largest_finite_positive_sign 7fefffffffffffff 3ae0000000000000 7fefffffffffffff 0000000000000000 7fefffffffffffff 0000000000000000 0 # x=0x1.fffffffffffffp+1023 y=0x1.0000000000000p-81
+largest_finite_negative_sign 7fefffffffffffff c500000000000000 ffefffffffffffff 0000000000000000 ffefffffffffffff 0000000000000000 0 # x=0x1.fffffffffffffp+1023 y=-0x1.0000000000000p+81
+negative_largest_finite_positive_sign ffefffffffffffff 3ae0000000000000 7fefffffffffffff 0000000000000000 7fefffffffffffff 0000000000000000 0 # x=-0x1.fffffffffffffp+1023 y=0x1.0000000000000p-81
+negative_largest_finite_negative_sign ffefffffffffffff c500000000000000 ffefffffffffffff 0000000000000000 ffefffffffffffff 0000000000000000 0 # x=-0x1.fffffffffffffp+1023 y=-0x1.0000000000000p+81
+positive_infinity_positive_sign 7ff0000000000000 3ae0000000000000 +inf 0000000000000000 +inf 0000000000000000 0 # x=inf y=0x1.0000000000000p-81
+positive_infinity_negative_sign 7ff0000000000000 c500000000000000 -inf 0000000000000000 -inf 0000000000000000 0 # x=inf y=-0x1.0000000000000p+81
+negative_infinity_positive_sign fff0000000000000 3ae0000000000000 +inf 0000000000000000 +inf 0000000000000000 0 # x=-inf y=0x1.0000000000000p-81
+negative_infinity_negative_sign fff0000000000000 c500000000000000 -inf 0000000000000000 -inf 0000000000000000 0 # x=-inf y=-0x1.0000000000000p+81
+quiet_nan_payload_positive_sign 7ff8abcdef135790 3ae0000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=0x1.0000000000000p-81
+quiet_nan_payload_negative_sign 7ff8abcdef135790 c500000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=-0x1.0000000000000p+81
+negative_quiet_nan_payload_positive_sign fff8abcdef135790 3ae0000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=0x1.0000000000000p-81
+negative_quiet_nan_payload_negative_sign fff8abcdef135790 c500000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=-0x1.0000000000000p+81
+signaling_nan_payload_positive_sign 7ff0000000010248 3ae0000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=0x1.0000000000000p-81
+signaling_nan_payload_negative_sign 7ff0000000010248 c500000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=-0x1.0000000000000p+81
+negative_signaling_nan_payload_positive_sign fff0000000010248 3ae0000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=0x1.0000000000000p-81
+negative_signaling_nan_payload_negative_sign fff0000000010248 c500000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=-0x1.0000000000000p+81
+ordinary_positive_sign 405b380000000000 3ae0000000000000 405b380000000000 0000000000000000 405b380000000000 0000000000000000 0 # x=0x1.b380000000000p+6 y=0x1.0000000000000p-81
+ordinary_negative_sign 405b380000000000 c500000000000000 c05b380000000000 0000000000000000 c05b380000000000 0000000000000000 0 # x=0x1.b380000000000p+6 y=-0x1.0000000000000p+81
+sign_from_negative_nan 401e800000000000 fff0000000010248 c01e800000000000 0000000000000000 c01e800000000000 0000000000000000 0 # x=0x1.e800000000000p+2 y=nan
+sign_from_negative_zero 401e800000000000 8000000000000000 c01e800000000000 0000000000000000 c01e800000000000 0000000000000000 0 # x=0x1.e800000000000p+2 y=-0x0.0p+0
+sign_from_positive_nan c01e800000000000 7ff8abcdef135790 401e800000000000 0000000000000000 401e800000000000 0000000000000000 0 # x=-0x1.e800000000000p+2 y=nan

+ 48 - 0
tests/dmath/cases/cos.txt

@@ -0,0 +1,48 @@
+# dmath_cos
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep dd5127d63bcdaf72
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+positive_zero 0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=0x0.0p+0 y=0x0.0p+0
+negative_zero 8000000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=-0x0.0p+0 y=0x0.0p+0
+least_subnormal 0000000000000001 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=0x0.0000000000001p-1022 y=0x0.0p+0
+negative_least_subnormal 8000000000000001 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=-0x0.0000000000001p-1022 y=0x0.0p+0
+third_subnormal 0000000000000003 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=0x0.0000000000003p-1022 y=0x0.0p+0
+negative_third_subnormal 8000000000000003 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=-0x0.0000000000003p-1022 y=0x0.0p+0
+largest_subnormal 000fffffffffffff 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=0x0.fffffffffffffp-1022 y=0x0.0p+0
+negative_largest_subnormal 800fffffffffffff 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=-0x0.fffffffffffffp-1022 y=0x0.0p+0
+least_normal 0010000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=0x1.0000000000000p-1022 y=0x0.0p+0
+negative_least_normal 8010000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=-0x1.0000000000000p-1022 y=0x0.0p+0
+largest_finite 7fefffffffffffff 0000000000000000 bfefffe62ecfab75 0000000000000000 bfefffe62ecfab75 0000000000000000 1 # x=0x1.fffffffffffffp+1023 y=0x0.0p+0
+negative_largest_finite ffefffffffffffff 0000000000000000 bfefffe62ecfab75 0000000000000000 bfefffe62ecfab75 0000000000000000 1 # x=-0x1.fffffffffffffp+1023 y=0x0.0p+0
+positive_infinity 7ff0000000000000 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=inf y=0x0.0p+0
+negative_infinity fff0000000000000 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=-inf y=0x0.0p+0
+quiet_nan_payload 7ff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+negative_quiet_nan_payload fff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+signaling_nan_payload 7ff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+negative_signaling_nan_payload fff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+small_positive_angle 3fd6000000000000 0000000000000000 3fee20bf49acd6c1 0000000000000000 3fee20bf49acd6c1 0000000000000000 1 # x=0x1.6000000000000p-2 y=0x0.0p+0
+small_negative_angle bfd6000000000000 0000000000000000 3fee20bf49acd6c1 0000000000000000 3fee20bf49acd6c1 0000000000000000 1 # x=-0x1.6000000000000p-2 y=0x0.0p+0
+moderate_positive_angle 4045e80000000000 0000000000000000 3fef8a30fe6ef96c 0000000000000000 3fef8a30fe6ef96c 0000000000000000 1 # x=0x1.5e80000000000p+5 y=0x0.0p+0
+moderate_negative_angle c045e80000000000 0000000000000000 3fef8a30fe6ef96c 0000000000000000 3fef8a30fe6ef96c 0000000000000000 1 # x=-0x1.5e80000000000p+5 y=0x0.0p+0
+large_reduction 428a5c739b18426f 0000000000000000 3fda2a49d24e0f94 0000000000000000 3fda2a49d24e0f94 0000000000000000 1 # x=0x1.a5c739b18426fp+41 y=0x0.0p+0
+very_large_reduction 72a73b4a82cf19de 0000000000000000 3fe4832d2f71ebb6 0000000000000000 3fe4832d2f71ebb6 0000000000000000 1 # x=0x1.73b4a82cf19dep+811 y=0x0.0p+0
+quarter_turn_kernel_below 3fe921fb54442d17 0000000000000000 3fe6a09e667f3bce 0000000000000000 3fe6a09e667f3bcd 0000000000000000 1 # x=0x1.921fb54442d17p-1 y=0x0.0p+0
+quarter_turn_kernel_at 3fe921fb54442d18 0000000000000000 3fe6a09e667f3bcd 0000000000000000 3fe6a09e667f3bcd 0000000000000000 1 # x=0x1.921fb54442d18p-1 y=0x0.0p+0
+quarter_turn_kernel_above 3fe921fb54442d19 0000000000000000 3fe6a09e667f3bcc 0000000000000000 3fe6a09e667f3bcc 0000000000000000 1 # x=0x1.921fb54442d19p-1 y=0x0.0p+0
+negative_quarter_turn_kernel_below bfe921fb54442d17 0000000000000000 3fe6a09e667f3bce 0000000000000000 3fe6a09e667f3bcd 0000000000000000 1 # x=-0x1.921fb54442d17p-1 y=0x0.0p+0
+negative_quarter_turn_kernel_at bfe921fb54442d18 0000000000000000 3fe6a09e667f3bcd 0000000000000000 3fe6a09e667f3bcd 0000000000000000 1 # x=-0x1.921fb54442d18p-1 y=0x0.0p+0
+negative_quarter_turn_kernel_above bfe921fb54442d19 0000000000000000 3fe6a09e667f3bcc 0000000000000000 3fe6a09e667f3bcc 0000000000000000 1 # x=-0x1.921fb54442d19p-1 y=0x0.0p+0
+medium_reduction_cutoff_below 413921faffffffff 0000000000000000 3fee483125700ac3 0000000000000000 3fee483125700ac3 0000000000000000 1 # x=0x1.921faffffffffp+20 y=0x0.0p+0
+medium_reduction_cutoff_at 413921fb00000000 0000000000000000 3fee4831257a62da 0000000000000000 3fee4831257a62da 0000000000000000 1 # x=0x1.921fb00000000p+20 y=0x0.0p+0
+medium_reduction_cutoff_above 413921fb00000001 0000000000000000 3fee48312584baf1 0000000000000000 3fee48312584baf1 0000000000000000 1 # x=0x1.921fb00000001p+20 y=0x0.0p+0
+negative_medium_reduction_cutoff_below c13921faffffffff 0000000000000000 3fee483125700ac3 0000000000000000 3fee483125700ac3 0000000000000000 1 # x=-0x1.921faffffffffp+20 y=0x0.0p+0
+negative_medium_reduction_cutoff_at c13921fb00000000 0000000000000000 3fee4831257a62da 0000000000000000 3fee4831257a62da 0000000000000000 1 # x=-0x1.921fb00000000p+20 y=0x0.0p+0
+negative_medium_reduction_cutoff_above c13921fb00000001 0000000000000000 3fee48312584baf1 0000000000000000 3fee48312584baf1 0000000000000000 1 # x=-0x1.921fb00000001p+20 y=0x0.0p+0
+tiny_cutoff_below 3e46a09dffffffff 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=0x1.6a09dffffffffp-27 y=0x0.0p+0
+tiny_cutoff_at 3e46a09e00000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=0x1.6a09e00000000p-27 y=0x0.0p+0
+tiny_cutoff_above 3e46a09e00000001 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=0x1.6a09e00000001p-27 y=0x0.0p+0
+negative_tiny_cutoff_below be46a09dffffffff 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=-0x1.6a09dffffffffp-27 y=0x0.0p+0
+negative_tiny_cutoff_at be46a09e00000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=-0x1.6a09e00000000p-27 y=0x0.0p+0
+negative_tiny_cutoff_above be46a09e00000001 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=-0x1.6a09e00000001p-27 y=0x0.0p+0

+ 55 - 0
tests/dmath/cases/exp.txt

@@ -0,0 +1,55 @@
+# dmath_exp
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep ecb25a4ce882ca62
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+positive_zero 0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=0x0.0p+0 y=0x0.0p+0
+negative_zero 8000000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=-0x0.0p+0 y=0x0.0p+0
+least_subnormal 0000000000000001 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=0x0.0000000000001p-1022 y=0x0.0p+0
+negative_least_subnormal 8000000000000001 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=-0x0.0000000000001p-1022 y=0x0.0p+0
+third_subnormal 0000000000000003 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=0x0.0000000000003p-1022 y=0x0.0p+0
+negative_third_subnormal 8000000000000003 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=-0x0.0000000000003p-1022 y=0x0.0p+0
+largest_subnormal 000fffffffffffff 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=0x0.fffffffffffffp-1022 y=0x0.0p+0
+negative_largest_subnormal 800fffffffffffff 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=-0x0.fffffffffffffp-1022 y=0x0.0p+0
+least_normal 0010000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=0x1.0000000000000p-1022 y=0x0.0p+0
+negative_least_normal 8010000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=-0x1.0000000000000p-1022 y=0x0.0p+0
+largest_finite 7fefffffffffffff 0000000000000000 +inf 0000000000000000 +inf 0000000000000000 1 # x=0x1.fffffffffffffp+1023 y=0x0.0p+0
+negative_largest_finite ffefffffffffffff 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 1 # x=-0x1.fffffffffffffp+1023 y=0x0.0p+0
+positive_infinity 7ff0000000000000 0000000000000000 +inf 0000000000000000 +inf 0000000000000000 1 # x=inf y=0x0.0p+0
+negative_infinity fff0000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 1 # x=-inf y=0x0.0p+0
+quiet_nan_payload 7ff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+negative_quiet_nan_payload fff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+signaling_nan_payload 7ff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+negative_signaling_nan_payload fff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+moderate_positive 4019400000000000 0000000000000000 40813b5fcefbb1cd 0000000000000000 40813b5fcefbb1cd 0000000000000000 1 # x=0x1.9400000000000p+2 y=0x0.0p+0
+moderate_negative c019400000000000 0000000000000000 3f5db6582cff7939 0000000000000000 3f5db6582cff7939 0000000000000000 1 # x=-0x1.9400000000000p+2 y=0x0.0p+0
+large_finite_result 4086230000000000 0000000000000000 7fcf5267b43fad1f 0000000000000000 7fcf5267b43fad1f 0000000000000000 1 # x=0x1.6230000000000p+9 y=0x0.0p+0
+subnormal_result c087150000000000 0000000000000000 000000000000014f 0000000000000000 000000000000014f 0000000000000000 1 # x=-0x1.7150000000000p+9 y=0x0.0p+0
+tiny_shortcut_below 3e2fffffffffffff 0000000000000000 3ff0000001000000 0000000000000000 3ff0000001000000 0000000000000000 1 # x=0x1.fffffffffffffp-29 y=0x0.0p+0
+tiny_shortcut_at 3e30000000000000 0000000000000000 3ff0000001000000 0000000000000000 3ff0000001000000 0000000000000000 1 # x=0x1.0000000000000p-28 y=0x0.0p+0
+tiny_shortcut_above 3e30000000000001 0000000000000000 3ff0000001000000 0000000000000000 3ff0000001000000 0000000000000000 1 # x=0x1.0000000000001p-28 y=0x0.0p+0
+negative_tiny_shortcut_below be2fffffffffffff 0000000000000000 3feffffffe000000 0000000000000000 3feffffffe000000 0000000000000000 1 # x=-0x1.fffffffffffffp-29 y=0x0.0p+0
+negative_tiny_shortcut_at be30000000000000 0000000000000000 3feffffffe000000 0000000000000000 3feffffffe000000 0000000000000000 1 # x=-0x1.0000000000000p-28 y=0x0.0p+0
+negative_tiny_shortcut_above be30000000000001 0000000000000000 3feffffffe000000 0000000000000000 3feffffffe000000 0000000000000000 1 # x=-0x1.0000000000001p-28 y=0x0.0p+0
+first_reduction_below 3fd62e42ffffffff 0000000000000000 3ff6a09e66dbc8d9 0000000000000000 3ff6a09e66dbc8d9 0000000000000000 1 # x=0x1.62e42ffffffffp-2 y=0x0.0p+0
+first_reduction_at 3fd62e4300000000 0000000000000000 3ff6a09e66dbc8da 0000000000000000 3ff6a09e66dbc8d9 0000000000000000 1 # x=0x1.62e4300000000p-2 y=0x0.0p+0
+first_reduction_above 3fd62e4300000001 0000000000000000 3ff6a09e66dbc8da 0000000000000000 3ff6a09e66dbc8da 0000000000000000 1 # x=0x1.62e4300000001p-2 y=0x0.0p+0
+negative_first_reduction_below bfd62e42ffffffff 0000000000000000 3fe6a09e6622aec0 0000000000000000 3fe6a09e6622aec0 0000000000000000 1 # x=-0x1.62e42ffffffffp-2 y=0x0.0p+0
+negative_first_reduction_at bfd62e4300000000 0000000000000000 3fe6a09e6622aec0 0000000000000000 3fe6a09e6622aec0 0000000000000000 1 # x=-0x1.62e4300000000p-2 y=0x0.0p+0
+negative_first_reduction_above bfd62e4300000001 0000000000000000 3fe6a09e6622aec0 0000000000000000 3fe6a09e6622aebf 0000000000000000 1 # x=-0x1.62e4300000001p-2 y=0x0.0p+0
+second_reduction_below 3ff0a2b1ffffffff 0000000000000000 4006a09e0d126a08 0000000000000000 4006a09e0d126a08 0000000000000000 1 # x=0x1.0a2b1ffffffffp+0 y=0x0.0p+0
+second_reduction_at 3ff0a2b200000000 0000000000000000 4006a09e0d126a0a 0000000000000000 4006a09e0d126a0a 0000000000000000 1 # x=0x1.0a2b200000000p+0 y=0x0.0p+0
+second_reduction_above 3ff0a2b200000001 0000000000000000 4006a09e0d126a0b 0000000000000000 4006a09e0d126a0b 0000000000000000 1 # x=0x1.0a2b200000001p+0 y=0x0.0p+0
+negative_second_reduction_below bff0a2b1ffffffff 0000000000000000 3fd6a09ebfec0ef2 0000000000000000 3fd6a09ebfec0ef2 0000000000000000 1 # x=-0x1.0a2b1ffffffffp+0 y=0x0.0p+0
+negative_second_reduction_at bff0a2b200000000 0000000000000000 3fd6a09ebfec0ef1 0000000000000000 3fd6a09ebfec0ef1 0000000000000000 1 # x=-0x1.0a2b200000000p+0 y=0x0.0p+0
+negative_second_reduction_above bff0a2b200000001 0000000000000000 3fd6a09ebfec0ef0 0000000000000000 3fd6a09ebfec0eef 0000000000000000 1 # x=-0x1.0a2b200000001p+0 y=0x0.0p+0
+overflow_boundary_below 40862e42fefa39ee 0000000000000000 7feffffffffffb2a 0000000000000000 7feffffffffffb2a 0000000000000000 1 # x=0x1.62e42fefa39eep+9 y=0x0.0p+0
+overflow_boundary_at 40862e42fefa39ef 0000000000000000 7fefffffffffff2a 0000000000000000 7fefffffffffff2a 0000000000000000 1 # x=0x1.62e42fefa39efp+9 y=0x0.0p+0
+overflow_boundary_above 40862e42fefa39f0 0000000000000000 +inf 0000000000000000 +inf 0000000000000000 1 # x=0x1.62e42fefa39f0p+9 y=0x0.0p+0
+negative_overflow_boundary_below c0862e42fefa39ee 0000000000000000 000400000000009b 0000000000000000 000400000000009b 0000000000000000 1 # x=-0x1.62e42fefa39eep+9 y=0x0.0p+0
+negative_overflow_boundary_at c0862e42fefa39ef 0000000000000000 000400000000001b 0000000000000000 000400000000001b 0000000000000000 1 # x=-0x1.62e42fefa39efp+9 y=0x0.0p+0
+negative_overflow_boundary_above c0862e42fefa39f0 0000000000000000 0003ffffffffff9b 0000000000000000 0003ffffffffff9b 0000000000000000 1 # x=-0x1.62e42fefa39f0p+9 y=0x0.0p+0
+underflow_threshold_below c0874910d52d3050 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 1 # x=-0x1.74910d52d3050p+9 y=0x0.0p+0
+underflow_threshold_at c0874910d52d3051 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 1 # x=-0x1.74910d52d3051p+9 y=0x0.0p+0
+underflow_threshold_above c0874910d52d3052 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 1 # x=-0x1.74910d52d3052p+9 y=0x0.0p+0

+ 32 - 0
tests/dmath/cases/exp10.txt

@@ -0,0 +1,32 @@
+# dmath_exp10
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep 7405e97ea9f32271
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+positive_zero 0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=0x0.0p+0 y=0x0.0p+0
+negative_zero 8000000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=-0x0.0p+0 y=0x0.0p+0
+least_subnormal 0000000000000001 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=0x0.0000000000001p-1022 y=0x0.0p+0
+negative_least_subnormal 8000000000000001 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=-0x0.0000000000001p-1022 y=0x0.0p+0
+third_subnormal 0000000000000003 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=0x0.0000000000003p-1022 y=0x0.0p+0
+negative_third_subnormal 8000000000000003 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=-0x0.0000000000003p-1022 y=0x0.0p+0
+largest_subnormal 000fffffffffffff 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=0x0.fffffffffffffp-1022 y=0x0.0p+0
+negative_largest_subnormal 800fffffffffffff 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=-0x0.fffffffffffffp-1022 y=0x0.0p+0
+least_normal 0010000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=0x1.0000000000000p-1022 y=0x0.0p+0
+negative_least_normal 8010000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=-0x1.0000000000000p-1022 y=0x0.0p+0
+largest_finite 7fefffffffffffff 0000000000000000 +inf 0000000000000000 +inf 0000000000000000 2 # x=0x1.fffffffffffffp+1023 y=0x0.0p+0
+negative_largest_finite ffefffffffffffff 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 2 # x=-0x1.fffffffffffffp+1023 y=0x0.0p+0
+positive_infinity 7ff0000000000000 0000000000000000 +inf 0000000000000000 +inf 0000000000000000 2 # x=inf y=0x0.0p+0
+negative_infinity fff0000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 2 # x=-inf y=0x0.0p+0
+quiet_nan_payload 7ff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 2 # x=nan y=0x0.0p+0
+negative_quiet_nan_payload fff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 2 # x=nan y=0x0.0p+0
+signaling_nan_payload 7ff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 2 # x=nan y=0x0.0p+0
+negative_signaling_nan_payload fff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 2 # x=nan y=0x0.0p+0
+exact_positive_power 4031000000000000 0000000000000000 4376345785d8a000 0000000000000000 4376345785d8a000 0000000000000000 2 # x=0x1.1000000000000p+4 y=0x0.0p+0
+negative_power c031000000000000 0000000000000000 3c670ef54646d496 0000000000000000 3c670ef54646d497 0000000000000000 2 # x=-0x1.1000000000000p+4 y=0x0.0p+0
+fractional_positive 4010c00000000000 0000000000000000 40ce13a1f40f260d 0000000000000000 40ce13a1f40f260d 0000000000000000 2 # x=0x1.0c00000000000p+2 y=0x0.0p+0
+fractional_negative c010c00000000000 0000000000000000 3f1105ed25e9b25e 0000000000000000 3f1105ed25e9b25e 0000000000000000 2 # x=-0x1.0c00000000000p+2 y=0x0.0p+0
+subnormal_result c073fc0000000000 0000000000000000 0000000000000e0f 0000000000000000 0000000000000e0f 0000000000000000 2 # x=-0x1.3fc0000000000p+8 y=0x0.0p+0
+overflow_below 40734413509f79fe 0000000000000000 7feffffffffffba1 0000000000000000 7feffffffffffba1 0000000000000000 2 # x=0x1.34413509f79fep+8 y=0x0.0p+0
+overflow_at 40734413509f79ff 0000000000000000 +inf 0000000000000000 +inf 0000000000000000 2 # x=0x1.34413509f79ffp+8 y=0x0.0p+0
+overflow_above 40734413509f7a00 0000000000000000 +inf 0000000000000000 +inf 0000000000000000 2 # x=0x1.34413509f7a00p+8 y=0x0.0p+0

+ 46 - 0
tests/dmath/cases/exp2.txt

@@ -0,0 +1,46 @@
+# dmath_exp2
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep 481ab13c2f5c0a46
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+positive_zero 0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=0x0.0p+0 y=0x0.0p+0
+negative_zero 8000000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=-0x0.0p+0 y=0x0.0p+0
+least_subnormal 0000000000000001 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=0x0.0000000000001p-1022 y=0x0.0p+0
+negative_least_subnormal 8000000000000001 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=-0x0.0000000000001p-1022 y=0x0.0p+0
+third_subnormal 0000000000000003 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=0x0.0000000000003p-1022 y=0x0.0p+0
+negative_third_subnormal 8000000000000003 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=-0x0.0000000000003p-1022 y=0x0.0p+0
+largest_subnormal 000fffffffffffff 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=0x0.fffffffffffffp-1022 y=0x0.0p+0
+negative_largest_subnormal 800fffffffffffff 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=-0x0.fffffffffffffp-1022 y=0x0.0p+0
+least_normal 0010000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=0x1.0000000000000p-1022 y=0x0.0p+0
+negative_least_normal 8010000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 1 # x=-0x1.0000000000000p-1022 y=0x0.0p+0
+largest_finite 7fefffffffffffff 0000000000000000 +inf 0000000000000000 +inf 0000000000000000 1 # x=0x1.fffffffffffffp+1023 y=0x0.0p+0
+negative_largest_finite ffefffffffffffff 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 1 # x=-0x1.fffffffffffffp+1023 y=0x0.0p+0
+positive_infinity 7ff0000000000000 0000000000000000 +inf 0000000000000000 +inf 0000000000000000 1 # x=inf y=0x0.0p+0
+negative_infinity fff0000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 1 # x=-inf y=0x0.0p+0
+quiet_nan_payload 7ff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+negative_quiet_nan_payload fff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+signaling_nan_payload 7ff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+negative_signaling_nan_payload fff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+fractional_positive 4028a00000000000 0000000000000000 40b3dea64c123422 0000000000000000 40b3dea64c123422 0000000000000000 1 # x=0x1.8a00000000000p+3 y=0x0.0p+0
+fractional_negative c028a00000000000 0000000000000000 3f29c49182a3f090 0000000000000000 3f29c49182a3f090 0000000000000000 1 # x=-0x1.8a00000000000p+3 y=0x0.0p+0
+exact_normal_power c08a780000000000 0000000000000000 0b00000000000000 0000000000000000 0b00000000000000 0000000000000000 1 # x=-0x1.a780000000000p+9 y=0x0.0p+0
+subnormal_power c090740000000000 0000000000000000 0000000000200000 0000000000000000 0000000000200000 0000000000000000 1 # x=-0x1.0740000000000p+10 y=0x0.0p+0
+table_midpoint_9_below 3fa2ffffffffffff 0000000000000000 3ff06ab99fa6407c 0000000000000000 3ff06ab99fa6407c 0000000000000000 1 # x=0x1.2ffffffffffffp-5 y=0x0.0p+0
+table_midpoint_9_at 3fa3000000000000 0000000000000000 3ff06ab99fa6407c 0000000000000000 3ff06ab99fa6407c 0000000000000000 1 # x=0x1.3000000000000p-5 y=0x0.0p+0
+table_midpoint_9_above 3fa3000000000001 0000000000000000 3ff06ab99fa6407c 0000000000000000 3ff06ab99fa6407c 0000000000000000 1 # x=0x1.3000000000001p-5 y=0x0.0p+0
+table_midpoint_67_below 3fd0dfffffffffff 0000000000000000 3ff3355f4fb45e20 0000000000000000 3ff3355f4fb45e20 0000000000000000 1 # x=0x1.0dfffffffffffp-2 y=0x0.0p+0
+table_midpoint_67_at 3fd0e00000000000 0000000000000000 3ff3355f4fb45e20 0000000000000000 3ff3355f4fb45e20 0000000000000000 1 # x=0x1.0e00000000000p-2 y=0x0.0p+0
+table_midpoint_67_above 3fd0e00000000001 0000000000000000 3ff3355f4fb45e20 0000000000000000 3ff3355f4fb45e20 0000000000000000 1 # x=0x1.0e00000000001p-2 y=0x0.0p+0
+table_midpoint_143_below 3fe1efffffffffff 0000000000000000 3ff798e56b7fcf03 0000000000000000 3ff798e56b7fcf03 0000000000000000 1 # x=0x1.1efffffffffffp-1 y=0x0.0p+0
+table_midpoint_143_at 3fe1f00000000000 0000000000000000 3ff798e56b7fcf03 0000000000000000 3ff798e56b7fcf03 0000000000000000 1 # x=0x1.1f00000000000p-1 y=0x0.0p+0
+table_midpoint_143_above 3fe1f00000000001 0000000000000000 3ff798e56b7fcf04 0000000000000000 3ff798e56b7fcf04 0000000000000000 1 # x=0x1.1f00000000001p-1 y=0x0.0p+0
+table_midpoint_219_below 3feb6fffffffffff 0000000000000000 3ffcfd1f95018d16 0000000000000000 3ffcfd1f95018d16 0000000000000000 1 # x=0x1.b6fffffffffffp-1 y=0x0.0p+0
+table_midpoint_219_at 3feb700000000000 0000000000000000 3ffcfd1f95018d17 0000000000000000 3ffcfd1f95018d17 0000000000000000 1 # x=0x1.b700000000000p-1 y=0x0.0p+0
+table_midpoint_219_above 3feb700000000001 0000000000000000 3ffcfd1f95018d17 0000000000000000 3ffcfd1f95018d17 0000000000000000 1 # x=0x1.b700000000001p-1 y=0x0.0p+0
+overflow_below 408fffffffffffff 0000000000000000 7feffffffffffd3a 0000000000000000 7feffffffffffd3a 0000000000000000 1 # x=0x1.fffffffffffffp+9 y=0x0.0p+0
+overflow_at 4090000000000000 0000000000000000 +inf 0000000000000000 +inf 0000000000000000 1 # x=0x1.0000000000000p+10 y=0x0.0p+0
+overflow_above 4090000000000001 0000000000000000 +inf 0000000000000000 +inf 0000000000000000 1 # x=0x1.0000000000001p+10 y=0x0.0p+0
+underflow_tie_below c090cbffffffffff 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 1 # x=-0x1.0cbffffffffffp+10 y=0x0.0p+0
+underflow_tie_at c090cc0000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 1 # x=-0x1.0cc0000000000p+10 y=0x0.0p+0
+underflow_tie_above c090cc0000000001 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 1 # x=-0x1.0cc0000000001p+10 y=0x0.0p+0

+ 26 - 0
tests/dmath/cases/fabs.txt

@@ -0,0 +1,26 @@
+# dmath_fabs
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep f0410218d93ab3ba
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+positive_zero 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.0p+0 y=0x0.0p+0
+negative_zero 8000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=-0x0.0p+0 y=0x0.0p+0
+least_subnormal 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=0x0.0000000000001p-1022 y=0x0.0p+0
+negative_least_subnormal 8000000000000001 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=-0x0.0000000000001p-1022 y=0x0.0p+0
+third_subnormal 0000000000000003 0000000000000000 0000000000000003 0000000000000000 0000000000000003 0000000000000000 0 # x=0x0.0000000000003p-1022 y=0x0.0p+0
+negative_third_subnormal 8000000000000003 0000000000000000 0000000000000003 0000000000000000 0000000000000003 0000000000000000 0 # x=-0x0.0000000000003p-1022 y=0x0.0p+0
+largest_subnormal 000fffffffffffff 0000000000000000 000fffffffffffff 0000000000000000 000fffffffffffff 0000000000000000 0 # x=0x0.fffffffffffffp-1022 y=0x0.0p+0
+negative_largest_subnormal 800fffffffffffff 0000000000000000 000fffffffffffff 0000000000000000 000fffffffffffff 0000000000000000 0 # x=-0x0.fffffffffffffp-1022 y=0x0.0p+0
+least_normal 0010000000000000 0000000000000000 0010000000000000 0000000000000000 0010000000000000 0000000000000000 0 # x=0x1.0000000000000p-1022 y=0x0.0p+0
+negative_least_normal 8010000000000000 0000000000000000 0010000000000000 0000000000000000 0010000000000000 0000000000000000 0 # x=-0x1.0000000000000p-1022 y=0x0.0p+0
+largest_finite 7fefffffffffffff 0000000000000000 7fefffffffffffff 0000000000000000 7fefffffffffffff 0000000000000000 0 # x=0x1.fffffffffffffp+1023 y=0x0.0p+0
+negative_largest_finite ffefffffffffffff 0000000000000000 7fefffffffffffff 0000000000000000 7fefffffffffffff 0000000000000000 0 # x=-0x1.fffffffffffffp+1023 y=0x0.0p+0
+positive_infinity 7ff0000000000000 0000000000000000 +inf 0000000000000000 +inf 0000000000000000 0 # x=inf y=0x0.0p+0
+negative_infinity fff0000000000000 0000000000000000 +inf 0000000000000000 +inf 0000000000000000 0 # x=-inf y=0x0.0p+0
+quiet_nan_payload 7ff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=0x0.0p+0
+negative_quiet_nan_payload fff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=0x0.0p+0
+signaling_nan_payload 7ff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=0x0.0p+0
+negative_signaling_nan_payload fff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=0x0.0p+0
+negative_fraction bfb9600000000000 0000000000000000 3fb9600000000000 0000000000000000 3fb9600000000000 0000000000000000 0 # x=-0x1.9600000000000p-4 y=0x0.0p+0
+negative_large_integral c5823456789abcde 0000000000000000 45823456789abcde 0000000000000000 45823456789abcde 0000000000000000 0 # x=-0x1.23456789abcdep+89 y=0x0.0p+0

+ 68 - 0
tests/dmath/cases/floor.txt

@@ -0,0 +1,68 @@
+# dmath_floor
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep 69946c59a7110e87
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+positive_zero 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.0p+0 y=0x0.0p+0
+negative_zero 8000000000000000 0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x0.0p+0 y=0x0.0p+0
+least_subnormal 0000000000000001 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.0000000000001p-1022 y=0x0.0p+0
+negative_least_subnormal 8000000000000001 0000000000000000 bff0000000000000 0000000000000000 bff0000000000000 0000000000000000 0 # x=-0x0.0000000000001p-1022 y=0x0.0p+0
+third_subnormal 0000000000000003 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.0000000000003p-1022 y=0x0.0p+0
+negative_third_subnormal 8000000000000003 0000000000000000 bff0000000000000 0000000000000000 bff0000000000000 0000000000000000 0 # x=-0x0.0000000000003p-1022 y=0x0.0p+0
+largest_subnormal 000fffffffffffff 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.fffffffffffffp-1022 y=0x0.0p+0
+negative_largest_subnormal 800fffffffffffff 0000000000000000 bff0000000000000 0000000000000000 bff0000000000000 0000000000000000 0 # x=-0x0.fffffffffffffp-1022 y=0x0.0p+0
+least_normal 0010000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x1.0000000000000p-1022 y=0x0.0p+0
+negative_least_normal 8010000000000000 0000000000000000 bff0000000000000 0000000000000000 bff0000000000000 0000000000000000 0 # x=-0x1.0000000000000p-1022 y=0x0.0p+0
+largest_finite 7fefffffffffffff 0000000000000000 7fefffffffffffff 0000000000000000 7fefffffffffffff 0000000000000000 0 # x=0x1.fffffffffffffp+1023 y=0x0.0p+0
+negative_largest_finite ffefffffffffffff 0000000000000000 ffefffffffffffff 0000000000000000 ffefffffffffffff 0000000000000000 0 # x=-0x1.fffffffffffffp+1023 y=0x0.0p+0
+positive_infinity 7ff0000000000000 0000000000000000 +inf 0000000000000000 +inf 0000000000000000 0 # x=inf y=0x0.0p+0
+negative_infinity fff0000000000000 0000000000000000 -inf 0000000000000000 -inf 0000000000000000 0 # x=-inf y=0x0.0p+0
+quiet_nan_payload 7ff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=0x0.0p+0
+negative_quiet_nan_payload fff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=0x0.0p+0
+signaling_nan_payload 7ff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=0x0.0p+0
+negative_signaling_nan_payload fff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=0x0.0p+0
+unit_below 3fefffffffffffff 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x1.fffffffffffffp-1 y=0x0.0p+0
+unit_at 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 0 # x=0x1.0000000000000p+0 y=0x0.0p+0
+unit_above 3ff0000000000001 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 0 # x=0x1.0000000000001p+0 y=0x0.0p+0
+negative_unit_below bfefffffffffffff 0000000000000000 bff0000000000000 0000000000000000 bff0000000000000 0000000000000000 0 # x=-0x1.fffffffffffffp-1 y=0x0.0p+0
+negative_unit_at bff0000000000000 0000000000000000 bff0000000000000 0000000000000000 bff0000000000000 0000000000000000 0 # x=-0x1.0000000000000p+0 y=0x0.0p+0
+negative_unit_above bff0000000000001 0000000000000000 c000000000000000 0000000000000000 c000000000000000 0000000000000000 0 # x=-0x1.0000000000001p+0 y=0x0.0p+0
+half_below 3fdfffffffffffff 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x1.fffffffffffffp-2 y=0x0.0p+0
+half_at 3fe0000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x1.0000000000000p-1 y=0x0.0p+0
+half_above 3fe0000000000001 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x1.0000000000001p-1 y=0x0.0p+0
+negative_half_below bfdfffffffffffff 0000000000000000 bff0000000000000 0000000000000000 bff0000000000000 0000000000000000 0 # x=-0x1.fffffffffffffp-2 y=0x0.0p+0
+negative_half_at bfe0000000000000 0000000000000000 bff0000000000000 0000000000000000 bff0000000000000 0000000000000000 0 # x=-0x1.0000000000000p-1 y=0x0.0p+0
+negative_half_above bfe0000000000001 0000000000000000 bff0000000000000 0000000000000000 bff0000000000000 0000000000000000 0 # x=-0x1.0000000000001p-1 y=0x0.0p+0
+word_split_below 412fffffffffffff 0000000000000000 412ffffe00000000 0000000000000000 412ffffe00000000 0000000000000000 0 # x=0x1.fffffffffffffp+19 y=0x0.0p+0
+word_split_at 4130000000000000 0000000000000000 4130000000000000 0000000000000000 4130000000000000 0000000000000000 0 # x=0x1.0000000000000p+20 y=0x0.0p+0
+word_split_above 4130000000000001 0000000000000000 4130000000000000 0000000000000000 4130000000000000 0000000000000000 0 # x=0x1.0000000000001p+20 y=0x0.0p+0
+negative_word_split_below c12fffffffffffff 0000000000000000 c130000000000000 0000000000000000 c130000000000000 0000000000000000 0 # x=-0x1.fffffffffffffp+19 y=0x0.0p+0
+negative_word_split_at c130000000000000 0000000000000000 c130000000000000 0000000000000000 c130000000000000 0000000000000000 0 # x=-0x1.0000000000000p+20 y=0x0.0p+0
+negative_word_split_above c130000000000001 0000000000000000 c130000100000000 0000000000000000 c130000100000000 0000000000000000 0 # x=-0x1.0000000000001p+20 y=0x0.0p+0
+signed32_below 41dfffffffffffff 0000000000000000 41dfffffffc00000 0000000000000000 41dfffffffc00000 0000000000000000 0 # x=0x1.fffffffffffffp+30 y=0x0.0p+0
+signed32_at 41e0000000000000 0000000000000000 41e0000000000000 0000000000000000 41e0000000000000 0000000000000000 0 # x=0x1.0000000000000p+31 y=0x0.0p+0
+signed32_above 41e0000000000001 0000000000000000 41e0000000000000 0000000000000000 41e0000000000000 0000000000000000 0 # x=0x1.0000000000001p+31 y=0x0.0p+0
+negative_signed32_below c1dfffffffffffff 0000000000000000 c1e0000000000000 0000000000000000 c1e0000000000000 0000000000000000 0 # x=-0x1.fffffffffffffp+30 y=0x0.0p+0
+negative_signed32_at c1e0000000000000 0000000000000000 c1e0000000000000 0000000000000000 c1e0000000000000 0000000000000000 0 # x=-0x1.0000000000000p+31 y=0x0.0p+0
+negative_signed32_above c1e0000000000001 0000000000000000 c1e0000000200000 0000000000000000 c1e0000000200000 0000000000000000 0 # x=-0x1.0000000000001p+31 y=0x0.0p+0
+last_fractional_binade_below 431fffffffffffff 0000000000000000 431ffffffffffffc 0000000000000000 431ffffffffffffc 0000000000000000 0 # x=0x1.fffffffffffffp+50 y=0x0.0p+0
+last_fractional_binade_at 4320000000000000 0000000000000000 4320000000000000 0000000000000000 4320000000000000 0000000000000000 0 # x=0x1.0000000000000p+51 y=0x0.0p+0
+last_fractional_binade_above 4320000000000001 0000000000000000 4320000000000000 0000000000000000 4320000000000000 0000000000000000 0 # x=0x1.0000000000001p+51 y=0x0.0p+0
+negative_last_fractional_binade_below c31fffffffffffff 0000000000000000 c320000000000000 0000000000000000 c320000000000000 0000000000000000 0 # x=-0x1.fffffffffffffp+50 y=0x0.0p+0
+negative_last_fractional_binade_at c320000000000000 0000000000000000 c320000000000000 0000000000000000 c320000000000000 0000000000000000 0 # x=-0x1.0000000000000p+51 y=0x0.0p+0
+negative_last_fractional_binade_above c320000000000001 0000000000000000 c320000000000002 0000000000000000 c320000000000002 0000000000000000 0 # x=-0x1.0000000000001p+51 y=0x0.0p+0
+integral_binade_below 432fffffffffffff 0000000000000000 432ffffffffffffe 0000000000000000 432ffffffffffffe 0000000000000000 0 # x=0x1.fffffffffffffp+51 y=0x0.0p+0
+integral_binade_at 4330000000000000 0000000000000000 4330000000000000 0000000000000000 4330000000000000 0000000000000000 0 # x=0x1.0000000000000p+52 y=0x0.0p+0
+integral_binade_above 4330000000000001 0000000000000000 4330000000000001 0000000000000000 4330000000000001 0000000000000000 0 # x=0x1.0000000000001p+52 y=0x0.0p+0
+negative_integral_binade_below c32fffffffffffff 0000000000000000 c330000000000000 0000000000000000 c330000000000000 0000000000000000 0 # x=-0x1.fffffffffffffp+51 y=0x0.0p+0
+negative_integral_binade_at c330000000000000 0000000000000000 c330000000000000 0000000000000000 c330000000000000 0000000000000000 0 # x=-0x1.0000000000000p+52 y=0x0.0p+0
+negative_integral_binade_above c330000000000001 0000000000000000 c330000000000001 0000000000000000 c330000000000001 0000000000000000 0 # x=-0x1.0000000000001p+52 y=0x0.0p+0
+signed64_below 43dfffffffffffff 0000000000000000 43dfffffffffffff 0000000000000000 43dfffffffffffff 0000000000000000 0 # x=0x1.fffffffffffffp+62 y=0x0.0p+0
+signed64_at 43e0000000000000 0000000000000000 43e0000000000000 0000000000000000 43e0000000000000 0000000000000000 0 # x=0x1.0000000000000p+63 y=0x0.0p+0
+signed64_above 43e0000000000001 0000000000000000 43e0000000000001 0000000000000000 43e0000000000001 0000000000000000 0 # x=0x1.0000000000001p+63 y=0x0.0p+0
+negative_signed64_below c3dfffffffffffff 0000000000000000 c3dfffffffffffff 0000000000000000 c3dfffffffffffff 0000000000000000 0 # x=-0x1.fffffffffffffp+62 y=0x0.0p+0
+negative_signed64_at c3e0000000000000 0000000000000000 c3e0000000000000 0000000000000000 c3e0000000000000 0000000000000000 0 # x=-0x1.0000000000000p+63 y=0x0.0p+0
+negative_signed64_above c3e0000000000001 0000000000000000 c3e0000000000001 0000000000000000 c3e0000000000001 0000000000000000 0 # x=-0x1.0000000000001p+63 y=0x0.0p+0
+down_from_positive_fraction 4037f00000000000 0000000000000000 4037000000000000 0000000000000000 4037000000000000 0000000000000000 0 # x=0x1.7f00000000000p+4 y=0x0.0p+0
+down_from_negative_fraction c037f00000000000 0000000000000000 c038000000000000 0000000000000000 c038000000000000 0000000000000000 0 # x=-0x1.7f00000000000p+4 y=0x0.0p+0

+ 27 - 0
tests/dmath/cases/fmax.txt

@@ -0,0 +1,27 @@
+# dmath_fmax
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep ab3537069a406f80
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+ordered_pair_0 0000000000000000 8000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.0p+0 y=-0x0.0p+0
+ordered_pair_1 8000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=-0x0.0p+0 y=0x0.0p+0
+ordered_pair_2 8000000000000000 8000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x0.0p+0 y=-0x0.0p+0
+ordered_pair_3 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.0p+0 y=0x0.0p+0
+ordered_pair_4 c01e800000000000 4009800000000000 4009800000000000 0000000000000000 4009800000000000 0000000000000000 0 # x=-0x1.e800000000000p+2 y=0x1.9800000000000p+1
+ordered_pair_5 0000000000000001 0000000000000003 0000000000000003 0000000000000000 0000000000000003 0000000000000000 0 # x=0x0.0000000000001p-1022 y=0x0.0000000000003p-1022
+ordered_pair_6 7ff0000000000000 4026400000000000 +inf 0000000000000000 +inf 0000000000000000 0 # x=inf y=0x1.6400000000000p+3
+ordered_pair_7 fff0000000000000 c026400000000000 c026400000000000 0000000000000000 c026400000000000 0000000000000000 0 # x=-inf y=-0x1.6400000000000p+3
+quiet_nan_payload_left 7ff8abcdef135790 402a800000000000 402a800000000000 0000000000000000 402a800000000000 0000000000000000 0 # x=nan y=0x1.a800000000000p+3
+quiet_nan_payload_right 402a800000000000 7ff8abcdef135790 402a800000000000 0000000000000000 402a800000000000 0000000000000000 0 # x=0x1.a800000000000p+3 y=nan
+quiet_nan_payload_both 7ff8abcdef135790 fff8abcdef135790 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=nan
+negative_quiet_nan_payload_left fff8abcdef135790 402a800000000000 402a800000000000 0000000000000000 402a800000000000 0000000000000000 0 # x=nan y=0x1.a800000000000p+3
+negative_quiet_nan_payload_right 402a800000000000 fff8abcdef135790 402a800000000000 0000000000000000 402a800000000000 0000000000000000 0 # x=0x1.a800000000000p+3 y=nan
+negative_quiet_nan_payload_both fff8abcdef135790 fff8abcdef135790 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=nan
+signaling_nan_payload_left 7ff0000000010248 402a800000000000 402a800000000000 0000000000000000 402a800000000000 0000000000000000 0 # x=nan y=0x1.a800000000000p+3
+signaling_nan_payload_right 402a800000000000 7ff0000000010248 402a800000000000 0000000000000000 402a800000000000 0000000000000000 0 # x=0x1.a800000000000p+3 y=nan
+signaling_nan_payload_both 7ff0000000010248 fff8abcdef135790 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=nan
+negative_signaling_nan_payload_left fff0000000010248 402a800000000000 402a800000000000 0000000000000000 402a800000000000 0000000000000000 0 # x=nan y=0x1.a800000000000p+3
+negative_signaling_nan_payload_right 402a800000000000 fff0000000010248 402a800000000000 0000000000000000 402a800000000000 0000000000000000 0 # x=0x1.a800000000000p+3 y=nan
+negative_signaling_nan_payload_both fff0000000010248 fff8abcdef135790 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=nan
+equal_positive_numbers 4033e00000000000 4033e00000000000 4033e00000000000 0000000000000000 4033e00000000000 0000000000000000 0 # x=0x1.3e00000000000p+4 y=0x1.3e00000000000p+4

+ 27 - 0
tests/dmath/cases/fmin.txt

@@ -0,0 +1,27 @@
+# dmath_fmin
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep d04c5dd56b25eefe
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+ordered_pair_0 0000000000000000 8000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=0x0.0p+0 y=-0x0.0p+0
+ordered_pair_1 8000000000000000 0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x0.0p+0 y=0x0.0p+0
+ordered_pair_2 8000000000000000 8000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x0.0p+0 y=-0x0.0p+0
+ordered_pair_3 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.0p+0 y=0x0.0p+0
+ordered_pair_4 c01e800000000000 4009800000000000 c01e800000000000 0000000000000000 c01e800000000000 0000000000000000 0 # x=-0x1.e800000000000p+2 y=0x1.9800000000000p+1
+ordered_pair_5 0000000000000001 0000000000000003 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=0x0.0000000000001p-1022 y=0x0.0000000000003p-1022
+ordered_pair_6 7ff0000000000000 4026400000000000 4026400000000000 0000000000000000 4026400000000000 0000000000000000 0 # x=inf y=0x1.6400000000000p+3
+ordered_pair_7 fff0000000000000 c026400000000000 -inf 0000000000000000 -inf 0000000000000000 0 # x=-inf y=-0x1.6400000000000p+3
+quiet_nan_payload_left 7ff8abcdef135790 402a800000000000 402a800000000000 0000000000000000 402a800000000000 0000000000000000 0 # x=nan y=0x1.a800000000000p+3
+quiet_nan_payload_right 402a800000000000 7ff8abcdef135790 402a800000000000 0000000000000000 402a800000000000 0000000000000000 0 # x=0x1.a800000000000p+3 y=nan
+quiet_nan_payload_both 7ff8abcdef135790 fff8abcdef135790 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=nan
+negative_quiet_nan_payload_left fff8abcdef135790 402a800000000000 402a800000000000 0000000000000000 402a800000000000 0000000000000000 0 # x=nan y=0x1.a800000000000p+3
+negative_quiet_nan_payload_right 402a800000000000 fff8abcdef135790 402a800000000000 0000000000000000 402a800000000000 0000000000000000 0 # x=0x1.a800000000000p+3 y=nan
+negative_quiet_nan_payload_both fff8abcdef135790 fff8abcdef135790 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=nan
+signaling_nan_payload_left 7ff0000000010248 402a800000000000 402a800000000000 0000000000000000 402a800000000000 0000000000000000 0 # x=nan y=0x1.a800000000000p+3
+signaling_nan_payload_right 402a800000000000 7ff0000000010248 402a800000000000 0000000000000000 402a800000000000 0000000000000000 0 # x=0x1.a800000000000p+3 y=nan
+signaling_nan_payload_both 7ff0000000010248 fff8abcdef135790 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=nan
+negative_signaling_nan_payload_left fff0000000010248 402a800000000000 402a800000000000 0000000000000000 402a800000000000 0000000000000000 0 # x=nan y=0x1.a800000000000p+3
+negative_signaling_nan_payload_right 402a800000000000 fff0000000010248 402a800000000000 0000000000000000 402a800000000000 0000000000000000 0 # x=0x1.a800000000000p+3 y=nan
+negative_signaling_nan_payload_both fff0000000010248 fff8abcdef135790 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=nan
+equal_negative_numbers c033e00000000000 c033e00000000000 c033e00000000000 0000000000000000 c033e00000000000 0000000000000000 0 # x=-0x1.3e00000000000p+4 y=-0x1.3e00000000000p+4

+ 52 - 0
tests/dmath/cases/fmod.txt

@@ -0,0 +1,52 @@
+# dmath_fmod
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep 2bf75fc2f5e2050b
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+positive_remainder 404ae00000000000 401e000000000000 3ff4000000000000 0000000000000000 3ff4000000000000 0000000000000000 0 # x=0x1.ae00000000000p+5 y=0x1.e000000000000p+2
+negative_remainder c04ae00000000000 401e000000000000 bff4000000000000 0000000000000000 bff4000000000000 0000000000000000 0 # x=-0x1.ae00000000000p+5 y=0x1.e000000000000p+2
+negative_divisor 404ae00000000000 c01e000000000000 3ff4000000000000 0000000000000000 3ff4000000000000 0000000000000000 0 # x=0x1.ae00000000000p+5 y=-0x1.e000000000000p+2
+both_negative c04ae00000000000 c01e000000000000 bff4000000000000 0000000000000000 bff4000000000000 0000000000000000 0 # x=-0x1.ae00000000000p+5 y=-0x1.e000000000000p+2
+positive_exact_multiple 404a400000000000 401e000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x1.a400000000000p+5 y=0x1.e000000000000p+2
+negative_exact_multiple c04a400000000000 401e000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x1.a400000000000p+5 y=0x1.e000000000000p+2
+quotient_exceeds_double 783abcdef0000000 07a7000000000000 079c000000000000 0000000000000000 079c000000000000 0000000000000000 0 # x=0x1.abcdef0000000p+900 y=0x1.7000000000000p-901
+subnormal_remainder 0010000000000001 0010000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=0x1.0000000000001p-1022 y=0x1.0000000000000p-1022
+subnormal_division 000000000000001d 0000000000000007 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=0x0.000000000001dp-1022 y=0x0.0000000000007p-1022
+negative_subnormal_division 800000000000001d 0000000000000007 8000000000000001 0000000000000000 8000000000000001 0000000000000000 0 # x=-0x0.000000000001dp-1022 y=0x0.0000000000007p-1022
+positive_zero_dividend 0000000000000000 401e000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.0p+0 y=0x1.e000000000000p+2
+positive_zero_divisor c04ae00000000000 0000000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=-0x1.ae00000000000p+5 y=0x0.0p+0
+negative_zero_dividend 8000000000000000 401e000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x0.0p+0 y=0x1.e000000000000p+2
+negative_zero_divisor c04ae00000000000 8000000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=-0x1.ae00000000000p+5 y=-0x0.0p+0
+least_subnormal_dividend 0000000000000001 401e000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=0x0.0000000000001p-1022 y=0x1.e000000000000p+2
+least_subnormal_divisor c04ae00000000000 0000000000000001 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x1.ae00000000000p+5 y=0x0.0000000000001p-1022
+negative_least_subnormal_dividend 8000000000000001 401e000000000000 8000000000000001 0000000000000000 8000000000000001 0000000000000000 0 # x=-0x0.0000000000001p-1022 y=0x1.e000000000000p+2
+negative_least_subnormal_divisor c04ae00000000000 8000000000000001 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x1.ae00000000000p+5 y=-0x0.0000000000001p-1022
+third_subnormal_dividend 0000000000000003 401e000000000000 0000000000000003 0000000000000000 0000000000000003 0000000000000000 0 # x=0x0.0000000000003p-1022 y=0x1.e000000000000p+2
+third_subnormal_divisor c04ae00000000000 0000000000000003 8000000000000002 0000000000000000 8000000000000002 0000000000000000 0 # x=-0x1.ae00000000000p+5 y=0x0.0000000000003p-1022
+negative_third_subnormal_dividend 8000000000000003 401e000000000000 8000000000000003 0000000000000000 8000000000000003 0000000000000000 0 # x=-0x0.0000000000003p-1022 y=0x1.e000000000000p+2
+negative_third_subnormal_divisor c04ae00000000000 8000000000000003 8000000000000002 0000000000000000 8000000000000002 0000000000000000 0 # x=-0x1.ae00000000000p+5 y=-0x0.0000000000003p-1022
+largest_subnormal_dividend 000fffffffffffff 401e000000000000 000fffffffffffff 0000000000000000 000fffffffffffff 0000000000000000 0 # x=0x0.fffffffffffffp-1022 y=0x1.e000000000000p+2
+largest_subnormal_divisor c04ae00000000000 000fffffffffffff 800000d700000000 0000000000000000 800000d700000000 0000000000000000 0 # x=-0x1.ae00000000000p+5 y=0x0.fffffffffffffp-1022
+negative_largest_subnormal_dividend 800fffffffffffff 401e000000000000 800fffffffffffff 0000000000000000 800fffffffffffff 0000000000000000 0 # x=-0x0.fffffffffffffp-1022 y=0x1.e000000000000p+2
+negative_largest_subnormal_divisor c04ae00000000000 800fffffffffffff 800000d700000000 0000000000000000 800000d700000000 0000000000000000 0 # x=-0x1.ae00000000000p+5 y=-0x0.fffffffffffffp-1022
+least_normal_dividend 0010000000000000 401e000000000000 0010000000000000 0000000000000000 0010000000000000 0000000000000000 0 # x=0x1.0000000000000p-1022 y=0x1.e000000000000p+2
+least_normal_divisor c04ae00000000000 0010000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x1.ae00000000000p+5 y=0x1.0000000000000p-1022
+negative_least_normal_dividend 8010000000000000 401e000000000000 8010000000000000 0000000000000000 8010000000000000 0000000000000000 0 # x=-0x1.0000000000000p-1022 y=0x1.e000000000000p+2
+negative_least_normal_divisor c04ae00000000000 8010000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x1.ae00000000000p+5 y=-0x1.0000000000000p-1022
+largest_finite_dividend 7fefffffffffffff 401e000000000000 3fe0000000000000 0000000000000000 3fe0000000000000 0000000000000000 0 # x=0x1.fffffffffffffp+1023 y=0x1.e000000000000p+2
+largest_finite_divisor c04ae00000000000 7fefffffffffffff c04ae00000000000 0000000000000000 c04ae00000000000 0000000000000000 0 # x=-0x1.ae00000000000p+5 y=0x1.fffffffffffffp+1023
+negative_largest_finite_dividend ffefffffffffffff 401e000000000000 bfe0000000000000 0000000000000000 bfe0000000000000 0000000000000000 0 # x=-0x1.fffffffffffffp+1023 y=0x1.e000000000000p+2
+negative_largest_finite_divisor c04ae00000000000 ffefffffffffffff c04ae00000000000 0000000000000000 c04ae00000000000 0000000000000000 0 # x=-0x1.ae00000000000p+5 y=-0x1.fffffffffffffp+1023
+positive_infinity_dividend 7ff0000000000000 401e000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=inf y=0x1.e000000000000p+2
+positive_infinity_divisor c04ae00000000000 7ff0000000000000 c04ae00000000000 0000000000000000 c04ae00000000000 0000000000000000 0 # x=-0x1.ae00000000000p+5 y=inf
+negative_infinity_dividend fff0000000000000 401e000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=-inf y=0x1.e000000000000p+2
+negative_infinity_divisor c04ae00000000000 fff0000000000000 c04ae00000000000 0000000000000000 c04ae00000000000 0000000000000000 0 # x=-0x1.ae00000000000p+5 y=-inf
+quiet_nan_payload_dividend 7ff8abcdef135790 401e000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=0x1.e000000000000p+2
+quiet_nan_payload_divisor c04ae00000000000 7ff8abcdef135790 nan 0000000000000000 nan 0000000000000000 0 # x=-0x1.ae00000000000p+5 y=nan
+negative_quiet_nan_payload_dividend fff8abcdef135790 401e000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=0x1.e000000000000p+2
+negative_quiet_nan_payload_divisor c04ae00000000000 fff8abcdef135790 nan 0000000000000000 nan 0000000000000000 0 # x=-0x1.ae00000000000p+5 y=nan
+signaling_nan_payload_dividend 7ff0000000010248 401e000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=0x1.e000000000000p+2
+signaling_nan_payload_divisor c04ae00000000000 7ff0000000010248 nan 0000000000000000 nan 0000000000000000 0 # x=-0x1.ae00000000000p+5 y=nan
+negative_signaling_nan_payload_dividend fff0000000010248 401e000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=0x1.e000000000000p+2
+negative_signaling_nan_payload_divisor c04ae00000000000 fff0000000010248 nan 0000000000000000 nan 0000000000000000 0 # x=-0x1.ae00000000000p+5 y=nan

+ 26 - 0
tests/dmath/cases/isfinite.txt

@@ -0,0 +1,26 @@
+# dmath_isfinite
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep 497cb7af0aedf945
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+positive_zero 0000000000000000 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=0x0.0p+0 y=0x0.0p+0
+negative_zero 8000000000000000 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=-0x0.0p+0 y=0x0.0p+0
+least_subnormal 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=0x0.0000000000001p-1022 y=0x0.0p+0
+negative_least_subnormal 8000000000000001 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=-0x0.0000000000001p-1022 y=0x0.0p+0
+third_subnormal 0000000000000003 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=0x0.0000000000003p-1022 y=0x0.0p+0
+negative_third_subnormal 8000000000000003 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=-0x0.0000000000003p-1022 y=0x0.0p+0
+largest_subnormal 000fffffffffffff 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=0x0.fffffffffffffp-1022 y=0x0.0p+0
+negative_largest_subnormal 800fffffffffffff 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=-0x0.fffffffffffffp-1022 y=0x0.0p+0
+least_normal 0010000000000000 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=0x1.0000000000000p-1022 y=0x0.0p+0
+negative_least_normal 8010000000000000 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=-0x1.0000000000000p-1022 y=0x0.0p+0
+largest_finite 7fefffffffffffff 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=0x1.fffffffffffffp+1023 y=0x0.0p+0
+negative_largest_finite ffefffffffffffff 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=-0x1.fffffffffffffp+1023 y=0x0.0p+0
+positive_infinity 7ff0000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=inf y=0x0.0p+0
+negative_infinity fff0000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=-inf y=0x0.0p+0
+quiet_nan_payload 7ff8abcdef135790 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=nan y=0x0.0p+0
+negative_quiet_nan_payload fff8abcdef135790 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=nan y=0x0.0p+0
+signaling_nan_payload 7ff0000000010248 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=nan y=0x0.0p+0
+negative_signaling_nan_payload fff0000000010248 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=nan y=0x0.0p+0
+ordinary_positive 424abc1230000000 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=0x1.abc1230000000p+37 y=0x0.0p+0
+ordinary_negative b762468000000000 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=-0x1.2468000000000p-137 y=0x0.0p+0

+ 26 - 0
tests/dmath/cases/isinf.txt

@@ -0,0 +1,26 @@
+# dmath_isinf
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep 7645daf3d8142325
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+positive_zero 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.0p+0 y=0x0.0p+0
+negative_zero 8000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=-0x0.0p+0 y=0x0.0p+0
+least_subnormal 0000000000000001 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.0000000000001p-1022 y=0x0.0p+0
+negative_least_subnormal 8000000000000001 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=-0x0.0000000000001p-1022 y=0x0.0p+0
+third_subnormal 0000000000000003 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.0000000000003p-1022 y=0x0.0p+0
+negative_third_subnormal 8000000000000003 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=-0x0.0000000000003p-1022 y=0x0.0p+0
+largest_subnormal 000fffffffffffff 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.fffffffffffffp-1022 y=0x0.0p+0
+negative_largest_subnormal 800fffffffffffff 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=-0x0.fffffffffffffp-1022 y=0x0.0p+0
+least_normal 0010000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x1.0000000000000p-1022 y=0x0.0p+0
+negative_least_normal 8010000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=-0x1.0000000000000p-1022 y=0x0.0p+0
+largest_finite 7fefffffffffffff 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x1.fffffffffffffp+1023 y=0x0.0p+0
+negative_largest_finite ffefffffffffffff 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=-0x1.fffffffffffffp+1023 y=0x0.0p+0
+positive_infinity 7ff0000000000000 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=inf y=0x0.0p+0
+negative_infinity fff0000000000000 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=-inf y=0x0.0p+0
+quiet_nan_payload 7ff8abcdef135790 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=nan y=0x0.0p+0
+negative_quiet_nan_payload fff8abcdef135790 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=nan y=0x0.0p+0
+signaling_nan_payload 7ff0000000010248 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=nan y=0x0.0p+0
+negative_signaling_nan_payload fff0000000010248 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=nan y=0x0.0p+0
+exponent_below_infinity 7fe0000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x1.0000000000000p+1023 y=0x0.0p+0
+first_nan_encoding 7ff0000000000001 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=nan y=0x0.0p+0

+ 26 - 0
tests/dmath/cases/isnan.txt

@@ -0,0 +1,26 @@
+# dmath_isnan
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep 9622f57ee0966c45
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+positive_zero 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.0p+0 y=0x0.0p+0
+negative_zero 8000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=-0x0.0p+0 y=0x0.0p+0
+least_subnormal 0000000000000001 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.0000000000001p-1022 y=0x0.0p+0
+negative_least_subnormal 8000000000000001 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=-0x0.0000000000001p-1022 y=0x0.0p+0
+third_subnormal 0000000000000003 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.0000000000003p-1022 y=0x0.0p+0
+negative_third_subnormal 8000000000000003 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=-0x0.0000000000003p-1022 y=0x0.0p+0
+largest_subnormal 000fffffffffffff 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.fffffffffffffp-1022 y=0x0.0p+0
+negative_largest_subnormal 800fffffffffffff 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=-0x0.fffffffffffffp-1022 y=0x0.0p+0
+least_normal 0010000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x1.0000000000000p-1022 y=0x0.0p+0
+negative_least_normal 8010000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=-0x1.0000000000000p-1022 y=0x0.0p+0
+largest_finite 7fefffffffffffff 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x1.fffffffffffffp+1023 y=0x0.0p+0
+negative_largest_finite ffefffffffffffff 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=-0x1.fffffffffffffp+1023 y=0x0.0p+0
+positive_infinity 7ff0000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=inf y=0x0.0p+0
+negative_infinity fff0000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=-inf y=0x0.0p+0
+quiet_nan_payload 7ff8abcdef135790 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=nan y=0x0.0p+0
+negative_quiet_nan_payload fff8abcdef135790 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=nan y=0x0.0p+0
+signaling_nan_payload 7ff0000000010248 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=nan y=0x0.0p+0
+negative_signaling_nan_payload fff0000000010248 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=nan y=0x0.0p+0
+all_fraction_bits_set 7fffffffffffffff 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=nan y=0x0.0p+0
+negative_all_bits_set ffffffffffffffff 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=nan y=0x0.0p+0

+ 30 - 0
tests/dmath/cases/isnormal.txt

@@ -0,0 +1,30 @@
+# dmath_isnormal
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep 3a58575cbc8f23a5
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+positive_zero 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.0p+0 y=0x0.0p+0
+negative_zero 8000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=-0x0.0p+0 y=0x0.0p+0
+least_subnormal 0000000000000001 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.0000000000001p-1022 y=0x0.0p+0
+negative_least_subnormal 8000000000000001 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=-0x0.0000000000001p-1022 y=0x0.0p+0
+third_subnormal 0000000000000003 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.0000000000003p-1022 y=0x0.0p+0
+negative_third_subnormal 8000000000000003 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=-0x0.0000000000003p-1022 y=0x0.0p+0
+largest_subnormal 000fffffffffffff 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.fffffffffffffp-1022 y=0x0.0p+0
+negative_largest_subnormal 800fffffffffffff 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=-0x0.fffffffffffffp-1022 y=0x0.0p+0
+least_normal 0010000000000000 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=0x1.0000000000000p-1022 y=0x0.0p+0
+negative_least_normal 8010000000000000 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=-0x1.0000000000000p-1022 y=0x0.0p+0
+largest_finite 7fefffffffffffff 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=0x1.fffffffffffffp+1023 y=0x0.0p+0
+negative_largest_finite ffefffffffffffff 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=-0x1.fffffffffffffp+1023 y=0x0.0p+0
+positive_infinity 7ff0000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=inf y=0x0.0p+0
+negative_infinity fff0000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=-inf y=0x0.0p+0
+quiet_nan_payload 7ff8abcdef135790 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=nan y=0x0.0p+0
+negative_quiet_nan_payload fff8abcdef135790 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=nan y=0x0.0p+0
+signaling_nan_payload 7ff0000000010248 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=nan y=0x0.0p+0
+negative_signaling_nan_payload fff0000000010248 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=nan y=0x0.0p+0
+normal_transition_below 000fffffffffffff 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.fffffffffffffp-1022 y=0x0.0p+0
+normal_transition_at 0010000000000000 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=0x1.0000000000000p-1022 y=0x0.0p+0
+normal_transition_above 0010000000000001 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=0x1.0000000000001p-1022 y=0x0.0p+0
+negative_normal_transition_below 800fffffffffffff 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=-0x0.fffffffffffffp-1022 y=0x0.0p+0
+negative_normal_transition_at 8010000000000000 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=-0x1.0000000000000p-1022 y=0x0.0p+0
+negative_normal_transition_above 8010000000000001 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=-0x1.0000000000001p-1022 y=0x0.0p+0

+ 33 - 0
tests/dmath/cases/log.txt

@@ -0,0 +1,33 @@
+# dmath_log
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep f4f35139ad63a3c8
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+positive_zero 0000000000000000 0000000000000000 -inf 0000000000000000 -inf 0000000000000000 1 # x=0x0.0p+0 y=0x0.0p+0
+negative_zero 8000000000000000 0000000000000000 -inf 0000000000000000 -inf 0000000000000000 1 # x=-0x0.0p+0 y=0x0.0p+0
+least_subnormal 0000000000000001 0000000000000000 c0874385446d71c3 0000000000000000 c0874385446d71c3 0000000000000000 1 # x=0x0.0000000000001p-1022 y=0x0.0p+0
+negative_least_subnormal 8000000000000001 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=-0x0.0000000000001p-1022 y=0x0.0p+0
+third_subnormal 0000000000000003 0000000000000000 c0873abb4f301b42 0000000000000000 c0873abb4f301b42 0000000000000000 1 # x=0x0.0000000000003p-1022 y=0x0.0p+0
+negative_third_subnormal 8000000000000003 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=-0x0.0000000000003p-1022 y=0x0.0p+0
+largest_subnormal 000fffffffffffff 0000000000000000 c086232bdd7abcd2 0000000000000000 c086232bdd7abcd2 0000000000000000 1 # x=0x0.fffffffffffffp-1022 y=0x0.0p+0
+negative_largest_subnormal 800fffffffffffff 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=-0x0.fffffffffffffp-1022 y=0x0.0p+0
+least_normal 0010000000000000 0000000000000000 c086232bdd7abcd2 0000000000000000 c086232bdd7abcd2 0000000000000000 1 # x=0x1.0000000000000p-1022 y=0x0.0p+0
+negative_least_normal 8010000000000000 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=-0x1.0000000000000p-1022 y=0x0.0p+0
+largest_finite 7fefffffffffffff 0000000000000000 40862e42fefa39ef 0000000000000000 40862e42fefa39ef 0000000000000000 1 # x=0x1.fffffffffffffp+1023 y=0x0.0p+0
+negative_largest_finite ffefffffffffffff 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=-0x1.fffffffffffffp+1023 y=0x0.0p+0
+positive_infinity 7ff0000000000000 0000000000000000 +inf 0000000000000000 +inf 0000000000000000 1 # x=inf y=0x0.0p+0
+negative_infinity fff0000000000000 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=-inf y=0x0.0p+0
+quiet_nan_payload 7ff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+negative_quiet_nan_payload fff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+signaling_nan_payload 7ff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+negative_signaling_nan_payload fff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+near_one_below 3fefffffffffffff 0000000000000000 bca0000000000000 0000000000000000 bca0000000000000 0000000000000000 1 # x=0x1.fffffffffffffp-1 y=0x0.0p+0
+near_one_at 3ff0000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 1 # x=0x1.0000000000000p+0 y=0x0.0p+0
+near_one_above 3ff0000000000001 0000000000000000 3cafffffffffffff 0000000000000000 3cafffffffffffff 0000000000000000 1 # x=0x1.0000000000001p+0 y=0x0.0p+0
+normalize_below 3ff6a09dffffffff 0000000000000000 3fd62e41dd1274cb 0000000000000000 3fd62e41dd1274cb 0000000000000000 1 # x=0x1.6a09dffffffffp+0 y=0x0.0p+0
+normalize_at 3ff6a09e00000000 0000000000000000 3fd62e41dd1274ce 0000000000000000 3fd62e41dd1274ce 0000000000000000 1 # x=0x1.6a09e00000000p+0 y=0x0.0p+0
+normalize_above 3ff6a09e00000001 0000000000000000 3fd62e41dd1274d1 0000000000000000 3fd62e41dd1274d1 0000000000000000 1 # x=0x1.6a09e00000001p+0 y=0x0.0p+0
+less_than_one 3fc6000000000000 0000000000000000 bffc2d018df03f36 0000000000000000 bffc2d018df03f36 0000000000000000 1 # x=0x1.6000000000000p-3 y=0x0.0p+0
+greater_than_one 4037900000000000 0000000000000000 400946f9f8055080 0000000000000000 400946f9f8055081 0000000000000000 1 # x=0x1.7900000000000p+4 y=0x0.0p+0
+wide_exponent 6d2a9bcdef012345 0000000000000000 407f5a770537865a 0000000000000000 407f5a770537865a 0000000000000000 1 # x=0x1.a9bcdef012345p+723 y=0x0.0p+0

+ 34 - 0
tests/dmath/cases/log10.txt

@@ -0,0 +1,34 @@
+# dmath_log10
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep 03d96661a4789ddd
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+positive_zero 0000000000000000 0000000000000000 -inf 0000000000000000 -inf 0000000000000000 1 # x=0x0.0p+0 y=0x0.0p+0
+negative_zero 8000000000000000 0000000000000000 -inf 0000000000000000 -inf 0000000000000000 1 # x=-0x0.0p+0 y=0x0.0p+0
+least_subnormal 0000000000000001 0000000000000000 c07434e6420f4374 0000000000000000 c07434e6420f4374 0000000000000000 1 # x=0x0.0000000000001p-1022 y=0x0.0p+0
+negative_least_subnormal 8000000000000001 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=-0x0.0000000000001p-1022 y=0x0.0p+0
+third_subnormal 0000000000000003 0000000000000000 c0742d43f829af7e 0000000000000000 c0742d43f829af7e 0000000000000000 1 # x=0x0.0000000000003p-1022 y=0x0.0p+0
+negative_third_subnormal 8000000000000003 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=-0x0.0000000000003p-1022 y=0x0.0p+0
+largest_subnormal 000fffffffffffff 0000000000000000 c0733a7146f72a42 0000000000000000 c0733a7146f72a42 0000000000000000 1 # x=0x0.fffffffffffffp-1022 y=0x0.0p+0
+negative_largest_subnormal 800fffffffffffff 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=-0x0.fffffffffffffp-1022 y=0x0.0p+0
+least_normal 0010000000000000 0000000000000000 c0733a7146f72a42 0000000000000000 c0733a7146f72a42 0000000000000000 1 # x=0x1.0000000000000p-1022 y=0x0.0p+0
+negative_least_normal 8010000000000000 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=-0x1.0000000000000p-1022 y=0x0.0p+0
+largest_finite 7fefffffffffffff 0000000000000000 40734413509f79ff 0000000000000000 40734413509f79ff 0000000000000000 1 # x=0x1.fffffffffffffp+1023 y=0x0.0p+0
+negative_largest_finite ffefffffffffffff 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=-0x1.fffffffffffffp+1023 y=0x0.0p+0
+positive_infinity 7ff0000000000000 0000000000000000 +inf 0000000000000000 +inf 0000000000000000 1 # x=inf y=0x0.0p+0
+negative_infinity fff0000000000000 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=-inf y=0x0.0p+0
+quiet_nan_payload 7ff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+negative_quiet_nan_payload fff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+signaling_nan_payload 7ff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+negative_signaling_nan_payload fff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+near_one_below 3fefffffffffffff 0000000000000000 bc8bcb7b1526e50f 0000000000000000 bc8bcb7b1526e50f 0000000000000000 1 # x=0x1.fffffffffffffp-1 y=0x0.0p+0
+near_one_at 3ff0000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 1 # x=0x1.0000000000000p+0 y=0x0.0p+0
+near_one_above 3ff0000000000001 0000000000000000 3c9bcb7b1526e50d 0000000000000000 3c9bcb7b1526e50d 0000000000000000 1 # x=0x1.0000000000001p+0 y=0x0.0p+0
+normalize_below 3ff6a09dffffffff 0000000000000000 3fc3441254d07a4b 0000000000000000 3fc3441254d07a4b 0000000000000000 1 # x=0x1.6a09dffffffffp+0 y=0x0.0p+0
+normalize_at 3ff6a09e00000000 0000000000000000 3fc3441254d07a4e 0000000000000000 3fc3441254d07a4e 0000000000000000 1 # x=0x1.6a09e00000000p+0 y=0x0.0p+0
+normalize_above 3ff6a09e00000001 0000000000000000 3fc3441254d07a50 0000000000000000 3fc3441254d07a50 0000000000000000 1 # x=0x1.6a09e00000001p+0 y=0x0.0p+0
+less_than_one 3fc6000000000000 0000000000000000 bfe87923313ce320 0000000000000000 bfe87923313ce320 0000000000000000 1 # x=0x1.6000000000000p-3 y=0x0.0p+0
+greater_than_one 4037900000000000 0000000000000000 3ff5f49e6487fc3a 0000000000000000 3ff5f49e6487fc3a 0000000000000000 1 # x=0x1.7900000000000p+4 y=0x0.0p+0
+decimal_power 416312d000000000 0000000000000000 401c000000000000 0000000000000000 401c000000000000 0000000000000000 1 # x=0x1.312d000000000p+23 y=0x0.0p+0
+small_decimal 3e60c6f7a0b5ed8d 0000000000000000 c01e05460931d620 0000000000000000 c01e05460931d620 0000000000000000 1 # x=0x1.0c6f7a0b5ed8dp-25 y=0x0.0p+0

+ 34 - 0
tests/dmath/cases/log2.txt

@@ -0,0 +1,34 @@
+# dmath_log2
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep 537fb9330277766b
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+positive_zero 0000000000000000 0000000000000000 -inf 0000000000000000 -inf 0000000000000000 1 # x=0x0.0p+0 y=0x0.0p+0
+negative_zero 8000000000000000 0000000000000000 -inf 0000000000000000 -inf 0000000000000000 1 # x=-0x0.0p+0 y=0x0.0p+0
+least_subnormal 0000000000000001 0000000000000000 c090c80000000000 0000000000000000 c090c80000000000 0000000000000000 1 # x=0x0.0000000000001p-1022 y=0x0.0p+0
+negative_least_subnormal 8000000000000001 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=-0x0.0000000000001p-1022 y=0x0.0p+0
+third_subnormal 0000000000000003 0000000000000000 c090c1a8ff971811 0000000000000000 c090c1a8ff971811 0000000000000000 1 # x=0x0.0000000000003p-1022 y=0x0.0p+0
+negative_third_subnormal 8000000000000003 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=-0x0.0000000000003p-1022 y=0x0.0p+0
+largest_subnormal 000fffffffffffff 0000000000000000 c08ff00000000000 0000000000000000 c08ff00000000000 0000000000000000 1 # x=0x0.fffffffffffffp-1022 y=0x0.0p+0
+negative_largest_subnormal 800fffffffffffff 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=-0x0.fffffffffffffp-1022 y=0x0.0p+0
+least_normal 0010000000000000 0000000000000000 c08ff00000000000 0000000000000000 c08ff00000000000 0000000000000000 1 # x=0x1.0000000000000p-1022 y=0x0.0p+0
+negative_least_normal 8010000000000000 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=-0x1.0000000000000p-1022 y=0x0.0p+0
+largest_finite 7fefffffffffffff 0000000000000000 4090000000000000 0000000000000000 4090000000000000 0000000000000000 1 # x=0x1.fffffffffffffp+1023 y=0x0.0p+0
+negative_largest_finite ffefffffffffffff 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=-0x1.fffffffffffffp+1023 y=0x0.0p+0
+positive_infinity 7ff0000000000000 0000000000000000 +inf 0000000000000000 +inf 0000000000000000 1 # x=inf y=0x0.0p+0
+negative_infinity fff0000000000000 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=-inf y=0x0.0p+0
+quiet_nan_payload 7ff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+negative_quiet_nan_payload fff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+signaling_nan_payload 7ff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+negative_signaling_nan_payload fff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+near_one_below 3fefffffffffffff 0000000000000000 bca71547652b82fe 0000000000000000 bca71547652b82fe 0000000000000000 1 # x=0x1.fffffffffffffp-1 y=0x0.0p+0
+near_one_at 3ff0000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 1 # x=0x1.0000000000000p+0 y=0x0.0p+0
+near_one_above 3ff0000000000001 0000000000000000 3cb71547652b82fd 0000000000000000 3cb71547652b82fd 0000000000000000 1 # x=0x1.0000000000001p+0 y=0x0.0p+0
+normalize_below 3ff6a09dffffffff 0000000000000000 3fdffffe5dc146cc 0000000000000000 3fdffffe5dc146cc 0000000000000000 1 # x=0x1.6a09dffffffffp+0 y=0x0.0p+0
+normalize_at 3ff6a09e00000000 0000000000000000 3fdffffe5dc146d0 0000000000000000 3fdffffe5dc146d0 0000000000000000 1 # x=0x1.6a09e00000000p+0 y=0x0.0p+0
+normalize_above 3ff6a09e00000001 0000000000000000 3fdffffe5dc146d4 0000000000000000 3fdffffe5dc146d4 0000000000000000 1 # x=0x1.6a09e00000001p+0 y=0x0.0p+0
+less_than_one 3fc6000000000000 0000000000000000 c004531583f9a2be 0000000000000000 c004531583f9a2be 0000000000000000 1 # x=0x1.6000000000000p-3 y=0x0.0p+0
+greater_than_one 4037900000000000 0000000000000000 40123bd2a3b39775 0000000000000000 40123bd2a3b39775 0000000000000000 1 # x=0x1.7900000000000p+4 y=0x0.0p+0
+exact_binary_power 0ce0000000000000 0000000000000000 c089880000000000 0000000000000000 c089880000000000 0000000000000000 1 # x=0x1.0000000000000p-817 y=0x0.0p+0
+exact_subnormal_power 0000000000200000 0000000000000000 c090740000000000 0000000000000000 c090740000000000 0000000000000000 1 # x=0x0.0000000200000p-1022 y=0x0.0p+0

+ 53 - 0
tests/dmath/cases/log_base.txt

@@ -0,0 +1,53 @@
+# dmath_log_base
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep 1c7f9575a557b7e6
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+base_above_one 4033600000000000 400a000000000000 40041e23ddab6742 0000000000000000 40041e23ddab6743 0000000000000000 3 # x=0x1.3600000000000p+4 y=0x1.a000000000000p+1
+base_below_one 4033600000000000 3fd4000000000000 c00462c9eb983411 0000000000000000 c00462c9eb983411 0000000000000000 3 # x=0x1.3600000000000p+4 y=0x1.4000000000000p-2
+argument_below_one 3fd4000000000000 400a000000000000 bfef943dc7baeb42 0000000000000000 bfef943dc7baeb43 0000000000000000 3 # x=0x1.4000000000000p-2 y=0x1.a000000000000p+1
+equal_base_and_argument 400a000000000000 400a000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 3 # x=0x1.a000000000000p+1 y=0x1.a000000000000p+1
+zero_result_sign 3ff0000000000000 3fd4000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 3 # x=0x1.0000000000000p+0 y=0x1.4000000000000p-2
+base_one_positive 4033600000000000 3ff0000000000000 +inf 0000000000000000 +inf 0000000000000000 3 # x=0x1.3600000000000p+4 y=0x1.0000000000000p+0
+base_one_negative 3fd4000000000000 3ff0000000000000 -inf 0000000000000000 -inf 0000000000000000 3 # x=0x1.4000000000000p-2 y=0x1.0000000000000p+0
+both_one 3ff0000000000000 3ff0000000000000 nan 0000000000000000 nan 0000000000000000 3 # x=0x1.0000000000000p+0 y=0x1.0000000000000p+0
+near_one_pair 3ff0000000000003 3ff0000000000007 3fdb6db6db6db6df 0000000000000000 3fdb6db6db6db6df 0000000000000000 3 # x=0x1.0000000000003p+0 y=0x1.0000000000007p+0
+positive_zero_argument 0000000000000000 400a000000000000 -inf 0000000000000000 -inf 0000000000000000 3 # x=0x0.0p+0 y=0x1.a000000000000p+1
+positive_zero_base 4033600000000000 0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 3 # x=0x1.3600000000000p+4 y=0x0.0p+0
+negative_zero_argument 8000000000000000 400a000000000000 -inf 0000000000000000 -inf 0000000000000000 3 # x=-0x0.0p+0 y=0x1.a000000000000p+1
+negative_zero_base 4033600000000000 8000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 3 # x=0x1.3600000000000p+4 y=-0x0.0p+0
+least_subnormal_argument 0000000000000001 400a000000000000 c083bccf89f010e7 0000000000000000 c083bccf89f010e8 0000000000000000 3 # x=0x0.0000000000001p-1022 y=0x1.a000000000000p+1
+least_subnormal_base 4033600000000000 0000000000000001 bf704ee61ea9d42b 0000000000000000 bf704ee61ea9d42b 0000000000000000 3 # x=0x1.3600000000000p+4 y=0x0.0000000000001p-1022
+negative_least_subnormal_argument 8000000000000001 400a000000000000 nan 0000000000000000 nan 0000000000000000 3 # x=-0x0.0000000000001p-1022 y=0x1.a000000000000p+1
+negative_least_subnormal_base 4033600000000000 8000000000000001 nan 0000000000000000 nan 0000000000000000 3 # x=0x1.3600000000000p+4 y=-0x0.0000000000001p-1022
+third_subnormal_argument 0000000000000003 400a000000000000 c083b55a9e721634 0000000000000000 c083b55a9e721634 0000000000000000 3 # x=0x0.0000000000003p-1022 y=0x1.a000000000000p+1
+third_subnormal_base 4033600000000000 0000000000000003 bf705511b383d651 0000000000000000 bf705511b383d651 0000000000000000 3 # x=0x1.3600000000000p+4 y=0x0.0000000000003p-1022
+negative_third_subnormal_argument 8000000000000003 400a000000000000 nan 0000000000000000 nan 0000000000000000 3 # x=-0x0.0000000000003p-1022 y=0x1.a000000000000p+1
+negative_third_subnormal_base 4033600000000000 8000000000000003 nan 0000000000000000 nan 0000000000000000 3 # x=0x1.3600000000000p+4 y=-0x0.0000000000003p-1022
+largest_subnormal_argument 000fffffffffffff 400a000000000000 c082c82b0843c988 0000000000000000 c082c82b0843c988 0000000000000000 3 # x=0x0.fffffffffffffp-1022 y=0x1.a000000000000p+1
+largest_subnormal_base 4033600000000000 000fffffffffffff bf712352042b34a1 0000000000000000 bf712352042b34a1 0000000000000000 3 # x=0x1.3600000000000p+4 y=0x0.fffffffffffffp-1022
+negative_largest_subnormal_argument 800fffffffffffff 400a000000000000 nan 0000000000000000 nan 0000000000000000 3 # x=-0x0.fffffffffffffp-1022 y=0x1.a000000000000p+1
+negative_largest_subnormal_base 4033600000000000 800fffffffffffff nan 0000000000000000 nan 0000000000000000 3 # x=0x1.3600000000000p+4 y=-0x0.fffffffffffffp-1022
+least_normal_argument 0010000000000000 400a000000000000 c082c82b0843c988 0000000000000000 c082c82b0843c988 0000000000000000 3 # x=0x1.0000000000000p-1022 y=0x1.a000000000000p+1
+least_normal_base 4033600000000000 0010000000000000 bf712352042b34a1 0000000000000000 bf712352042b34a1 0000000000000000 3 # x=0x1.3600000000000p+4 y=0x1.0000000000000p-1022
+negative_least_normal_argument 8010000000000000 400a000000000000 nan 0000000000000000 nan 0000000000000000 3 # x=-0x1.0000000000000p-1022 y=0x1.a000000000000p+1
+negative_least_normal_base 4033600000000000 8010000000000000 nan 0000000000000000 nan 0000000000000000 3 # x=0x1.3600000000000p+4 y=-0x1.0000000000000p-1022
+largest_finite_argument 7fefffffffffffff 400a000000000000 4082d193d22cdff8 0000000000000000 4082d193d22cdff8 0000000000000000 3 # x=0x1.fffffffffffffp+1023 y=0x1.a000000000000p+1
+largest_finite_base 4033600000000000 7fefffffffffffff 3f711ac05b291f07 0000000000000000 3f711ac05b291f07 0000000000000000 3 # x=0x1.3600000000000p+4 y=0x1.fffffffffffffp+1023
+negative_largest_finite_argument ffefffffffffffff 400a000000000000 nan 0000000000000000 nan 0000000000000000 3 # x=-0x1.fffffffffffffp+1023 y=0x1.a000000000000p+1
+negative_largest_finite_base 4033600000000000 ffefffffffffffff nan 0000000000000000 nan 0000000000000000 3 # x=0x1.3600000000000p+4 y=-0x1.fffffffffffffp+1023
+positive_infinity_argument 7ff0000000000000 400a000000000000 +inf 0000000000000000 +inf 0000000000000000 3 # x=inf y=0x1.a000000000000p+1
+positive_infinity_base 4033600000000000 7ff0000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 3 # x=0x1.3600000000000p+4 y=inf
+negative_infinity_argument fff0000000000000 400a000000000000 nan 0000000000000000 nan 0000000000000000 3 # x=-inf y=0x1.a000000000000p+1
+negative_infinity_base 4033600000000000 fff0000000000000 nan 0000000000000000 nan 0000000000000000 3 # x=0x1.3600000000000p+4 y=-inf
+quiet_nan_payload_argument 7ff8abcdef135790 400a000000000000 nan 0000000000000000 nan 0000000000000000 3 # x=nan y=0x1.a000000000000p+1
+quiet_nan_payload_base 4033600000000000 7ff8abcdef135790 nan 0000000000000000 nan 0000000000000000 3 # x=0x1.3600000000000p+4 y=nan
+negative_quiet_nan_payload_argument fff8abcdef135790 400a000000000000 nan 0000000000000000 nan 0000000000000000 3 # x=nan y=0x1.a000000000000p+1
+negative_quiet_nan_payload_base 4033600000000000 fff8abcdef135790 nan 0000000000000000 nan 0000000000000000 3 # x=0x1.3600000000000p+4 y=nan
+signaling_nan_payload_argument 7ff0000000010248 400a000000000000 nan 0000000000000000 nan 0000000000000000 3 # x=nan y=0x1.a000000000000p+1
+signaling_nan_payload_base 4033600000000000 7ff0000000010248 nan 0000000000000000 nan 0000000000000000 3 # x=0x1.3600000000000p+4 y=nan
+negative_signaling_nan_payload_argument fff0000000010248 400a000000000000 nan 0000000000000000 nan 0000000000000000 3 # x=nan y=0x1.a000000000000p+1
+negative_signaling_nan_payload_base 4033600000000000 fff0000000010248 nan 0000000000000000 nan 0000000000000000 3 # x=0x1.3600000000000p+4 y=nan
+both_infinite 7ff0000000000000 7ff0000000000000 nan 0000000000000000 nan 0000000000000000 3 # x=inf y=inf
+both_zero 0000000000000000 0000000000000000 nan 0000000000000000 nan 0000000000000000 3 # x=0x0.0p+0 y=0x0.0p+0

+ 69 - 0
tests/dmath/cases/modf.txt

@@ -0,0 +1,69 @@
+# dmath_modf
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep c0ce491f711d62b2
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+positive_zero 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.0p+0 y=0x0.0p+0
+negative_zero 8000000000000000 0000000000000000 8000000000000000 8000000000000000 8000000000000000 8000000000000000 0 # x=-0x0.0p+0 y=0x0.0p+0
+least_subnormal 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0 # x=0x0.0000000000001p-1022 y=0x0.0p+0
+negative_least_subnormal 8000000000000001 0000000000000000 8000000000000001 8000000000000000 8000000000000001 8000000000000000 0 # x=-0x0.0000000000001p-1022 y=0x0.0p+0
+third_subnormal 0000000000000003 0000000000000000 0000000000000003 0000000000000000 0000000000000003 0000000000000000 0 # x=0x0.0000000000003p-1022 y=0x0.0p+0
+negative_third_subnormal 8000000000000003 0000000000000000 8000000000000003 8000000000000000 8000000000000003 8000000000000000 0 # x=-0x0.0000000000003p-1022 y=0x0.0p+0
+largest_subnormal 000fffffffffffff 0000000000000000 000fffffffffffff 0000000000000000 000fffffffffffff 0000000000000000 0 # x=0x0.fffffffffffffp-1022 y=0x0.0p+0
+negative_largest_subnormal 800fffffffffffff 0000000000000000 800fffffffffffff 8000000000000000 800fffffffffffff 8000000000000000 0 # x=-0x0.fffffffffffffp-1022 y=0x0.0p+0
+least_normal 0010000000000000 0000000000000000 0010000000000000 0000000000000000 0010000000000000 0000000000000000 0 # x=0x1.0000000000000p-1022 y=0x0.0p+0
+negative_least_normal 8010000000000000 0000000000000000 8010000000000000 8000000000000000 8010000000000000 8000000000000000 0 # x=-0x1.0000000000000p-1022 y=0x0.0p+0
+largest_finite 7fefffffffffffff 0000000000000000 0000000000000000 7fefffffffffffff 0000000000000000 7fefffffffffffff 0 # x=0x1.fffffffffffffp+1023 y=0x0.0p+0
+negative_largest_finite ffefffffffffffff 0000000000000000 8000000000000000 ffefffffffffffff 8000000000000000 ffefffffffffffff 0 # x=-0x1.fffffffffffffp+1023 y=0x0.0p+0
+positive_infinity 7ff0000000000000 0000000000000000 0000000000000000 +inf 0000000000000000 +inf 0 # x=inf y=0x0.0p+0
+negative_infinity fff0000000000000 0000000000000000 8000000000000000 -inf 8000000000000000 -inf 0 # x=-inf y=0x0.0p+0
+quiet_nan_payload 7ff8abcdef135790 0000000000000000 nan nan nan nan 0 # x=nan y=0x0.0p+0
+negative_quiet_nan_payload fff8abcdef135790 0000000000000000 nan nan nan nan 0 # x=nan y=0x0.0p+0
+signaling_nan_payload 7ff0000000010248 0000000000000000 nan nan nan nan 0 # x=nan y=0x0.0p+0
+negative_signaling_nan_payload fff0000000010248 0000000000000000 nan nan nan nan 0 # x=nan y=0x0.0p+0
+unit_below 3fefffffffffffff 0000000000000000 3fefffffffffffff 0000000000000000 3fefffffffffffff 0000000000000000 0 # x=0x1.fffffffffffffp-1 y=0x0.0p+0
+unit_at 3ff0000000000000 0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0 # x=0x1.0000000000000p+0 y=0x0.0p+0
+unit_above 3ff0000000000001 0000000000000000 3cb0000000000000 3ff0000000000000 3cb0000000000000 3ff0000000000000 0 # x=0x1.0000000000001p+0 y=0x0.0p+0
+negative_unit_below bfefffffffffffff 0000000000000000 bfefffffffffffff 8000000000000000 bfefffffffffffff 8000000000000000 0 # x=-0x1.fffffffffffffp-1 y=0x0.0p+0
+negative_unit_at bff0000000000000 0000000000000000 8000000000000000 bff0000000000000 8000000000000000 bff0000000000000 0 # x=-0x1.0000000000000p+0 y=0x0.0p+0
+negative_unit_above bff0000000000001 0000000000000000 bcb0000000000000 bff0000000000000 bcb0000000000000 bff0000000000000 0 # x=-0x1.0000000000001p+0 y=0x0.0p+0
+half_below 3fdfffffffffffff 0000000000000000 3fdfffffffffffff 0000000000000000 3fdfffffffffffff 0000000000000000 0 # x=0x1.fffffffffffffp-2 y=0x0.0p+0
+half_at 3fe0000000000000 0000000000000000 3fe0000000000000 0000000000000000 3fe0000000000000 0000000000000000 0 # x=0x1.0000000000000p-1 y=0x0.0p+0
+half_above 3fe0000000000001 0000000000000000 3fe0000000000001 0000000000000000 3fe0000000000001 0000000000000000 0 # x=0x1.0000000000001p-1 y=0x0.0p+0
+negative_half_below bfdfffffffffffff 0000000000000000 bfdfffffffffffff 8000000000000000 bfdfffffffffffff 8000000000000000 0 # x=-0x1.fffffffffffffp-2 y=0x0.0p+0
+negative_half_at bfe0000000000000 0000000000000000 bfe0000000000000 8000000000000000 bfe0000000000000 8000000000000000 0 # x=-0x1.0000000000000p-1 y=0x0.0p+0
+negative_half_above bfe0000000000001 0000000000000000 bfe0000000000001 8000000000000000 bfe0000000000001 8000000000000000 0 # x=-0x1.0000000000001p-1 y=0x0.0p+0
+word_split_below 412fffffffffffff 0000000000000000 3feffffffff00000 412ffffe00000000 3feffffffff00000 412ffffe00000000 0 # x=0x1.fffffffffffffp+19 y=0x0.0p+0
+word_split_at 4130000000000000 0000000000000000 0000000000000000 4130000000000000 0000000000000000 4130000000000000 0 # x=0x1.0000000000000p+20 y=0x0.0p+0
+word_split_above 4130000000000001 0000000000000000 3df0000000000000 4130000000000000 3df0000000000000 4130000000000000 0 # x=0x1.0000000000001p+20 y=0x0.0p+0
+negative_word_split_below c12fffffffffffff 0000000000000000 bfeffffffff00000 c12ffffe00000000 bfeffffffff00000 c12ffffe00000000 0 # x=-0x1.fffffffffffffp+19 y=0x0.0p+0
+negative_word_split_at c130000000000000 0000000000000000 8000000000000000 c130000000000000 8000000000000000 c130000000000000 0 # x=-0x1.0000000000000p+20 y=0x0.0p+0
+negative_word_split_above c130000000000001 0000000000000000 bdf0000000000000 c130000000000000 bdf0000000000000 c130000000000000 0 # x=-0x1.0000000000001p+20 y=0x0.0p+0
+signed32_below 41dfffffffffffff 0000000000000000 3fefffff80000000 41dfffffffc00000 3fefffff80000000 41dfffffffc00000 0 # x=0x1.fffffffffffffp+30 y=0x0.0p+0
+signed32_at 41e0000000000000 0000000000000000 0000000000000000 41e0000000000000 0000000000000000 41e0000000000000 0 # x=0x1.0000000000000p+31 y=0x0.0p+0
+signed32_above 41e0000000000001 0000000000000000 3ea0000000000000 41e0000000000000 3ea0000000000000 41e0000000000000 0 # x=0x1.0000000000001p+31 y=0x0.0p+0
+negative_signed32_below c1dfffffffffffff 0000000000000000 bfefffff80000000 c1dfffffffc00000 bfefffff80000000 c1dfffffffc00000 0 # x=-0x1.fffffffffffffp+30 y=0x0.0p+0
+negative_signed32_at c1e0000000000000 0000000000000000 8000000000000000 c1e0000000000000 8000000000000000 c1e0000000000000 0 # x=-0x1.0000000000000p+31 y=0x0.0p+0
+negative_signed32_above c1e0000000000001 0000000000000000 bea0000000000000 c1e0000000000000 bea0000000000000 c1e0000000000000 0 # x=-0x1.0000000000001p+31 y=0x0.0p+0
+last_fractional_binade_below 431fffffffffffff 0000000000000000 3fe8000000000000 431ffffffffffffc 3fe8000000000000 431ffffffffffffc 0 # x=0x1.fffffffffffffp+50 y=0x0.0p+0
+last_fractional_binade_at 4320000000000000 0000000000000000 0000000000000000 4320000000000000 0000000000000000 4320000000000000 0 # x=0x1.0000000000000p+51 y=0x0.0p+0
+last_fractional_binade_above 4320000000000001 0000000000000000 3fe0000000000000 4320000000000000 3fe0000000000000 4320000000000000 0 # x=0x1.0000000000001p+51 y=0x0.0p+0
+negative_last_fractional_binade_below c31fffffffffffff 0000000000000000 bfe8000000000000 c31ffffffffffffc bfe8000000000000 c31ffffffffffffc 0 # x=-0x1.fffffffffffffp+50 y=0x0.0p+0
+negative_last_fractional_binade_at c320000000000000 0000000000000000 8000000000000000 c320000000000000 8000000000000000 c320000000000000 0 # x=-0x1.0000000000000p+51 y=0x0.0p+0
+negative_last_fractional_binade_above c320000000000001 0000000000000000 bfe0000000000000 c320000000000000 bfe0000000000000 c320000000000000 0 # x=-0x1.0000000000001p+51 y=0x0.0p+0
+integral_binade_below 432fffffffffffff 0000000000000000 3fe0000000000000 432ffffffffffffe 3fe0000000000000 432ffffffffffffe 0 # x=0x1.fffffffffffffp+51 y=0x0.0p+0
+integral_binade_at 4330000000000000 0000000000000000 0000000000000000 4330000000000000 0000000000000000 4330000000000000 0 # x=0x1.0000000000000p+52 y=0x0.0p+0
+integral_binade_above 4330000000000001 0000000000000000 0000000000000000 4330000000000001 0000000000000000 4330000000000001 0 # x=0x1.0000000000001p+52 y=0x0.0p+0
+negative_integral_binade_below c32fffffffffffff 0000000000000000 bfe0000000000000 c32ffffffffffffe bfe0000000000000 c32ffffffffffffe 0 # x=-0x1.fffffffffffffp+51 y=0x0.0p+0
+negative_integral_binade_at c330000000000000 0000000000000000 8000000000000000 c330000000000000 8000000000000000 c330000000000000 0 # x=-0x1.0000000000000p+52 y=0x0.0p+0
+negative_integral_binade_above c330000000000001 0000000000000000 8000000000000000 c330000000000001 8000000000000000 c330000000000001 0 # x=-0x1.0000000000001p+52 y=0x0.0p+0
+signed64_below 43dfffffffffffff 0000000000000000 0000000000000000 43dfffffffffffff 0000000000000000 43dfffffffffffff 0 # x=0x1.fffffffffffffp+62 y=0x0.0p+0
+signed64_at 43e0000000000000 0000000000000000 0000000000000000 43e0000000000000 0000000000000000 43e0000000000000 0 # x=0x1.0000000000000p+63 y=0x0.0p+0
+signed64_above 43e0000000000001 0000000000000000 0000000000000000 43e0000000000001 0000000000000000 43e0000000000001 0 # x=0x1.0000000000001p+63 y=0x0.0p+0
+negative_signed64_below c3dfffffffffffff 0000000000000000 8000000000000000 c3dfffffffffffff 8000000000000000 c3dfffffffffffff 0 # x=-0x1.fffffffffffffp+62 y=0x0.0p+0
+negative_signed64_at c3e0000000000000 0000000000000000 8000000000000000 c3e0000000000000 8000000000000000 c3e0000000000000 0 # x=-0x1.0000000000000p+63 y=0x0.0p+0
+negative_signed64_above c3e0000000000001 0000000000000000 8000000000000000 c3e0000000000001 8000000000000000 c3e0000000000001 0 # x=-0x1.0000000000001p+63 y=0x0.0p+0
+split_positive 40603a0000000000 0000000000000000 3fea000000000000 4060200000000000 3fea000000000000 4060200000000000 0 # x=0x1.03a0000000000p+7 y=0x0.0p+0
+split_negative c0603a0000000000 0000000000000000 bfea000000000000 c060200000000000 bfea000000000000 c060200000000000 0 # x=-0x1.03a0000000000p+7 y=0x0.0p+0
+exact_negative_integer c060200000000000 0000000000000000 8000000000000000 c060200000000000 8000000000000000 c060200000000000 0 # x=-0x1.0200000000000p+7 y=0x0.0p+0

+ 99 - 0
tests/dmath/cases/pow.txt

@@ -0,0 +1,99 @@
+# dmath_pow
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep e4a43209f0c19324
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+positive_fractional 400a800000000000 4001800000000000 402b788511b19c85 0000000000000000 402b788511b19c85 0000000000000000 2 # x=0x1.a800000000000p+1 y=0x1.1800000000000p+1
+negative_odd_integer c00a800000000000 401c000000000000 c0b11823d7dfd000 0000000000000000 c0b11823d7dfd000 0000000000000000 2 # x=-0x1.a800000000000p+1 y=0x1.c000000000000p+2
+negative_even_integer c00a800000000000 4018000000000000 4094a4653ea40000 0000000000000000 4094a4653ea40000 0000000000000000 2 # x=-0x1.a800000000000p+1 y=0x1.8000000000000p+2
+negative_reciprocal c00a800000000000 c01c000000000000 bf2df396239c3a45 0000000000000000 bf2df396239c3a45 0000000000000000 2 # x=-0x1.a800000000000p+1 y=-0x1.c000000000000p+2
+negative_fractional_domain c00a800000000000 4001800000000000 nan 0000000000000000 nan 0000000000000000 2 # x=-0x1.a800000000000p+1 y=0x1.1800000000000p+1
+square_shortcut 404abcdef1234567 4000000000000000 40a65745097be819 0000000000000000 40a65745097be819 0000000000000000 2 # x=0x1.abcdef1234567p+5 y=0x1.0000000000000p+1
+cube_shortcut 404abcdef1234567 4008000000000000 4102aac47315362b 0000000000000000 4102aac47315362b 0000000000000000 2 # x=0x1.abcdef1234567p+5 y=0x1.8000000000000p+1
+fourth_power_shortcut 404abcdef1234567 4010000000000000 415f31d9da05c393 0000000000000000 415f31d9da05c394 0000000000000000 2 # x=0x1.abcdef1234567p+5 y=0x1.0000000000000p+2
+sqrt_shortcut 4037900000000000 3fe0000000000000 40136a9ef26f762f 0000000000000000 40136a9ef26f762f 0000000000000000 2 # x=0x1.7900000000000p+4 y=0x1.0000000000000p-1
+reciprocal_shortcut 4037900000000000 bff0000000000000 3fa5babcc647fa91 0000000000000000 3fa5babcc647fa91 0000000000000000 2 # x=0x1.7900000000000p+4 y=-0x1.0000000000000p+0
+near_one_large_positive 3ff0000000000003 4300000000000000 3ff747a513dbef6a 0000000000000000 3ff747a513dbef6a 0000000000000000 2 # x=0x1.0000000000003p+0 y=0x1.0000000000000p+49
+near_one_large_negative 3feffffffffffffb c300000000000000 3ff5de9176045ff6 0000000000000000 3ff5de9176045ff6 0000000000000000 2 # x=0x1.ffffffffffffbp-1 y=-0x1.0000000000000p+49
+finite_overflow 401e800000000000 40b0000000000000 +inf 0000000000000000 +inf 0000000000000000 2 # x=0x1.e800000000000p+2 y=0x1.0000000000000p+12
+finite_underflow 401e800000000000 c0b0000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 2 # x=0x1.e800000000000p+2 y=-0x1.0000000000000p+12
+negative_odd_overflow c01e800000000000 40b0010000000000 -inf 0000000000000000 -inf 0000000000000000 2 # x=-0x1.e800000000000p+2 y=0x1.0010000000000p+12
+negative_odd_underflow c01e800000000000 c0b0010000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 2 # x=-0x1.e800000000000p+2 y=-0x1.0010000000000p+12
+largest_odd_exponent bff0000000000000 433fffffffffffff bff0000000000000 0000000000000000 bff0000000000000 0000000000000000 2 # x=-0x1.0000000000000p+0 y=0x1.fffffffffffffp+52
+first_even_only_binade bff0000000000000 4340000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=-0x1.0000000000000p+0 y=0x1.0000000000000p+53
+positive_zero_odd_power 0000000000000000 401c000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 2 # x=0x0.0p+0 y=0x1.c000000000000p+2
+positive_zero_negative_odd_power 0000000000000000 c01c000000000000 +inf 0000000000000000 +inf 0000000000000000 2 # x=0x0.0p+0 y=-0x1.c000000000000p+2
+positive_zero_zero_power 0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=0x0.0p+0 y=0x0.0p+0
+positive_zero_exponent 400a800000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=0x1.a800000000000p+1 y=0x0.0p+0
+negative_zero_odd_power 8000000000000000 401c000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 2 # x=-0x0.0p+0 y=0x1.c000000000000p+2
+negative_zero_negative_odd_power 8000000000000000 c01c000000000000 -inf 0000000000000000 -inf 0000000000000000 2 # x=-0x0.0p+0 y=-0x1.c000000000000p+2
+negative_zero_zero_power 8000000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=-0x0.0p+0 y=0x0.0p+0
+negative_zero_exponent 400a800000000000 8000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=0x1.a800000000000p+1 y=-0x0.0p+0
+least_subnormal_odd_power 0000000000000001 401c000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 2 # x=0x0.0000000000001p-1022 y=0x1.c000000000000p+2
+least_subnormal_negative_odd_power 0000000000000001 c01c000000000000 +inf 0000000000000000 +inf 0000000000000000 2 # x=0x0.0000000000001p-1022 y=-0x1.c000000000000p+2
+least_subnormal_zero_power 0000000000000001 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=0x0.0000000000001p-1022 y=0x0.0p+0
+least_subnormal_exponent 400a800000000000 0000000000000001 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=0x1.a800000000000p+1 y=0x0.0000000000001p-1022
+negative_least_subnormal_odd_power 8000000000000001 401c000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 2 # x=-0x0.0000000000001p-1022 y=0x1.c000000000000p+2
+negative_least_subnormal_negative_odd_power 8000000000000001 c01c000000000000 -inf 0000000000000000 -inf 0000000000000000 2 # x=-0x0.0000000000001p-1022 y=-0x1.c000000000000p+2
+negative_least_subnormal_zero_power 8000000000000001 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=-0x0.0000000000001p-1022 y=0x0.0p+0
+negative_least_subnormal_exponent 400a800000000000 8000000000000001 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=0x1.a800000000000p+1 y=-0x0.0000000000001p-1022
+third_subnormal_odd_power 0000000000000003 401c000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 2 # x=0x0.0000000000003p-1022 y=0x1.c000000000000p+2
+third_subnormal_negative_odd_power 0000000000000003 c01c000000000000 +inf 0000000000000000 +inf 0000000000000000 2 # x=0x0.0000000000003p-1022 y=-0x1.c000000000000p+2
+third_subnormal_zero_power 0000000000000003 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=0x0.0000000000003p-1022 y=0x0.0p+0
+third_subnormal_exponent 400a800000000000 0000000000000003 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=0x1.a800000000000p+1 y=0x0.0000000000003p-1022
+negative_third_subnormal_odd_power 8000000000000003 401c000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 2 # x=-0x0.0000000000003p-1022 y=0x1.c000000000000p+2
+negative_third_subnormal_negative_odd_power 8000000000000003 c01c000000000000 -inf 0000000000000000 -inf 0000000000000000 2 # x=-0x0.0000000000003p-1022 y=-0x1.c000000000000p+2
+negative_third_subnormal_zero_power 8000000000000003 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=-0x0.0000000000003p-1022 y=0x0.0p+0
+negative_third_subnormal_exponent 400a800000000000 8000000000000003 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=0x1.a800000000000p+1 y=-0x0.0000000000003p-1022
+largest_subnormal_odd_power 000fffffffffffff 401c000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 2 # x=0x0.fffffffffffffp-1022 y=0x1.c000000000000p+2
+largest_subnormal_negative_odd_power 000fffffffffffff c01c000000000000 +inf 0000000000000000 +inf 0000000000000000 2 # x=0x0.fffffffffffffp-1022 y=-0x1.c000000000000p+2
+largest_subnormal_zero_power 000fffffffffffff 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=0x0.fffffffffffffp-1022 y=0x0.0p+0
+largest_subnormal_exponent 400a800000000000 000fffffffffffff 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=0x1.a800000000000p+1 y=0x0.fffffffffffffp-1022
+negative_largest_subnormal_odd_power 800fffffffffffff 401c000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 2 # x=-0x0.fffffffffffffp-1022 y=0x1.c000000000000p+2
+negative_largest_subnormal_negative_odd_power 800fffffffffffff c01c000000000000 -inf 0000000000000000 -inf 0000000000000000 2 # x=-0x0.fffffffffffffp-1022 y=-0x1.c000000000000p+2
+negative_largest_subnormal_zero_power 800fffffffffffff 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=-0x0.fffffffffffffp-1022 y=0x0.0p+0
+negative_largest_subnormal_exponent 400a800000000000 800fffffffffffff 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=0x1.a800000000000p+1 y=-0x0.fffffffffffffp-1022
+least_normal_odd_power 0010000000000000 401c000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 2 # x=0x1.0000000000000p-1022 y=0x1.c000000000000p+2
+least_normal_negative_odd_power 0010000000000000 c01c000000000000 +inf 0000000000000000 +inf 0000000000000000 2 # x=0x1.0000000000000p-1022 y=-0x1.c000000000000p+2
+least_normal_zero_power 0010000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=0x1.0000000000000p-1022 y=0x0.0p+0
+least_normal_exponent 400a800000000000 0010000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=0x1.a800000000000p+1 y=0x1.0000000000000p-1022
+negative_least_normal_odd_power 8010000000000000 401c000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 2 # x=-0x1.0000000000000p-1022 y=0x1.c000000000000p+2
+negative_least_normal_negative_odd_power 8010000000000000 c01c000000000000 -inf 0000000000000000 -inf 0000000000000000 2 # x=-0x1.0000000000000p-1022 y=-0x1.c000000000000p+2
+negative_least_normal_zero_power 8010000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=-0x1.0000000000000p-1022 y=0x0.0p+0
+negative_least_normal_exponent 400a800000000000 8010000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=0x1.a800000000000p+1 y=-0x1.0000000000000p-1022
+largest_finite_odd_power 7fefffffffffffff 401c000000000000 +inf 0000000000000000 +inf 0000000000000000 2 # x=0x1.fffffffffffffp+1023 y=0x1.c000000000000p+2
+largest_finite_negative_odd_power 7fefffffffffffff c01c000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 2 # x=0x1.fffffffffffffp+1023 y=-0x1.c000000000000p+2
+largest_finite_zero_power 7fefffffffffffff 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=0x1.fffffffffffffp+1023 y=0x0.0p+0
+largest_finite_exponent 400a800000000000 7fefffffffffffff +inf 0000000000000000 +inf 0000000000000000 2 # x=0x1.a800000000000p+1 y=0x1.fffffffffffffp+1023
+negative_largest_finite_odd_power ffefffffffffffff 401c000000000000 -inf 0000000000000000 -inf 0000000000000000 2 # x=-0x1.fffffffffffffp+1023 y=0x1.c000000000000p+2
+negative_largest_finite_negative_odd_power ffefffffffffffff c01c000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 2 # x=-0x1.fffffffffffffp+1023 y=-0x1.c000000000000p+2
+negative_largest_finite_zero_power ffefffffffffffff 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=-0x1.fffffffffffffp+1023 y=0x0.0p+0
+negative_largest_finite_exponent 400a800000000000 ffefffffffffffff 0000000000000000 0000000000000000 0000000000000000 0000000000000000 2 # x=0x1.a800000000000p+1 y=-0x1.fffffffffffffp+1023
+positive_infinity_odd_power 7ff0000000000000 401c000000000000 +inf 0000000000000000 +inf 0000000000000000 2 # x=inf y=0x1.c000000000000p+2
+positive_infinity_negative_odd_power 7ff0000000000000 c01c000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 2 # x=inf y=-0x1.c000000000000p+2
+positive_infinity_zero_power 7ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=inf y=0x0.0p+0
+positive_infinity_exponent 400a800000000000 7ff0000000000000 +inf 0000000000000000 +inf 0000000000000000 2 # x=0x1.a800000000000p+1 y=inf
+negative_infinity_odd_power fff0000000000000 401c000000000000 -inf 0000000000000000 -inf 0000000000000000 2 # x=-inf y=0x1.c000000000000p+2
+negative_infinity_negative_odd_power fff0000000000000 c01c000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 2 # x=-inf y=-0x1.c000000000000p+2
+negative_infinity_zero_power fff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=-inf y=0x0.0p+0
+negative_infinity_exponent 400a800000000000 fff0000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 2 # x=0x1.a800000000000p+1 y=-inf
+quiet_nan_payload_odd_power 7ff8abcdef135790 401c000000000000 nan 0000000000000000 nan 0000000000000000 2 # x=nan y=0x1.c000000000000p+2
+quiet_nan_payload_negative_odd_power 7ff8abcdef135790 c01c000000000000 nan 0000000000000000 nan 0000000000000000 2 # x=nan y=-0x1.c000000000000p+2
+quiet_nan_payload_zero_power 7ff8abcdef135790 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=nan y=0x0.0p+0
+quiet_nan_payload_exponent 400a800000000000 7ff8abcdef135790 nan 0000000000000000 nan 0000000000000000 2 # x=0x1.a800000000000p+1 y=nan
+negative_quiet_nan_payload_odd_power fff8abcdef135790 401c000000000000 nan 0000000000000000 nan 0000000000000000 2 # x=nan y=0x1.c000000000000p+2
+negative_quiet_nan_payload_negative_odd_power fff8abcdef135790 c01c000000000000 nan 0000000000000000 nan 0000000000000000 2 # x=nan y=-0x1.c000000000000p+2
+negative_quiet_nan_payload_zero_power fff8abcdef135790 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=nan y=0x0.0p+0
+negative_quiet_nan_payload_exponent 400a800000000000 fff8abcdef135790 nan 0000000000000000 nan 0000000000000000 2 # x=0x1.a800000000000p+1 y=nan
+signaling_nan_payload_odd_power 7ff0000000010248 401c000000000000 nan 0000000000000000 nan 0000000000000000 2 # x=nan y=0x1.c000000000000p+2
+signaling_nan_payload_negative_odd_power 7ff0000000010248 c01c000000000000 nan 0000000000000000 nan 0000000000000000 2 # x=nan y=-0x1.c000000000000p+2
+signaling_nan_payload_zero_power 7ff0000000010248 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=nan y=0x0.0p+0
+signaling_nan_payload_exponent 400a800000000000 7ff0000000010248 nan 0000000000000000 nan 0000000000000000 2 # x=0x1.a800000000000p+1 y=nan
+negative_signaling_nan_payload_odd_power fff0000000010248 401c000000000000 nan 0000000000000000 nan 0000000000000000 2 # x=nan y=0x1.c000000000000p+2
+negative_signaling_nan_payload_negative_odd_power fff0000000010248 c01c000000000000 nan 0000000000000000 nan 0000000000000000 2 # x=nan y=-0x1.c000000000000p+2
+negative_signaling_nan_payload_zero_power fff0000000010248 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=nan y=0x0.0p+0
+negative_signaling_nan_payload_exponent 400a800000000000 fff0000000010248 nan 0000000000000000 nan 0000000000000000 2 # x=0x1.a800000000000p+1 y=nan
+one_to_nan 3ff0000000000000 fff0000000010248 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=0x1.0000000000000p+0 y=nan
+negative_one_to_infinity bff0000000000000 7ff0000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 2 # x=-0x1.0000000000000p+0 y=inf
+negative_zero_fractional_pole 8000000000000000 bfd0000000000000 +inf 0000000000000000 +inf 0000000000000000 2 # x=-0x0.0p+0 y=-0x1.0000000000000p-2

+ 48 - 0
tests/dmath/cases/sin.txt

@@ -0,0 +1,48 @@
+# dmath_sin
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep 83e4ca3079c8879b
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+positive_zero 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 1 # x=0x0.0p+0 y=0x0.0p+0
+negative_zero 8000000000000000 0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 1 # x=-0x0.0p+0 y=0x0.0p+0
+least_subnormal 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 1 # x=0x0.0000000000001p-1022 y=0x0.0p+0
+negative_least_subnormal 8000000000000001 0000000000000000 8000000000000001 0000000000000000 8000000000000001 0000000000000000 1 # x=-0x0.0000000000001p-1022 y=0x0.0p+0
+third_subnormal 0000000000000003 0000000000000000 0000000000000003 0000000000000000 0000000000000003 0000000000000000 1 # x=0x0.0000000000003p-1022 y=0x0.0p+0
+negative_third_subnormal 8000000000000003 0000000000000000 8000000000000003 0000000000000000 8000000000000003 0000000000000000 1 # x=-0x0.0000000000003p-1022 y=0x0.0p+0
+largest_subnormal 000fffffffffffff 0000000000000000 000fffffffffffff 0000000000000000 000fffffffffffff 0000000000000000 1 # x=0x0.fffffffffffffp-1022 y=0x0.0p+0
+negative_largest_subnormal 800fffffffffffff 0000000000000000 800fffffffffffff 0000000000000000 800fffffffffffff 0000000000000000 1 # x=-0x0.fffffffffffffp-1022 y=0x0.0p+0
+least_normal 0010000000000000 0000000000000000 0010000000000000 0000000000000000 0010000000000000 0000000000000000 1 # x=0x1.0000000000000p-1022 y=0x0.0p+0
+negative_least_normal 8010000000000000 0000000000000000 8010000000000000 0000000000000000 8010000000000000 0000000000000000 1 # x=-0x1.0000000000000p-1022 y=0x0.0p+0
+largest_finite 7fefffffffffffff 0000000000000000 3f7452fc98b34e97 0000000000000000 3f7452fc98b34e97 0000000000000000 1 # x=0x1.fffffffffffffp+1023 y=0x0.0p+0
+negative_largest_finite ffefffffffffffff 0000000000000000 bf7452fc98b34e97 0000000000000000 bf7452fc98b34e97 0000000000000000 1 # x=-0x1.fffffffffffffp+1023 y=0x0.0p+0
+positive_infinity 7ff0000000000000 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=inf y=0x0.0p+0
+negative_infinity fff0000000000000 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=-inf y=0x0.0p+0
+quiet_nan_payload 7ff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+negative_quiet_nan_payload fff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+signaling_nan_payload 7ff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+negative_signaling_nan_payload fff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+small_positive_angle 3fd6000000000000 0000000000000000 3fd591bc9fa2f597 0000000000000000 3fd591bc9fa2f597 0000000000000000 1 # x=0x1.6000000000000p-2 y=0x0.0p+0
+small_negative_angle bfd6000000000000 0000000000000000 bfd591bc9fa2f597 0000000000000000 bfd591bc9fa2f597 0000000000000000 1 # x=-0x1.6000000000000p-2 y=0x0.0p+0
+moderate_positive_angle 4045e80000000000 0000000000000000 bfc5a13747aff14f 0000000000000000 bfc5a13747aff14f 0000000000000000 1 # x=0x1.5e80000000000p+5 y=0x0.0p+0
+moderate_negative_angle c045e80000000000 0000000000000000 3fc5a13747aff14f 0000000000000000 3fc5a13747aff14f 0000000000000000 1 # x=-0x1.5e80000000000p+5 y=0x0.0p+0
+large_reduction 428a5c739b18426f 0000000000000000 3fed341a0bb536bf 0000000000000000 3fed341a0bb536bf 0000000000000000 1 # x=0x1.a5c739b18426fp+41 y=0x0.0p+0
+very_large_reduction 72a73b4a82cf19de 0000000000000000 3fe88f9b8b914182 0000000000000000 3fe88f9b8b914182 0000000000000000 1 # x=0x1.73b4a82cf19dep+811 y=0x0.0p+0
+quarter_turn_kernel_below 3fe921fb54442d17 0000000000000000 3fe6a09e667f3bcc 0000000000000000 3fe6a09e667f3bcc 0000000000000000 1 # x=0x1.921fb54442d17p-1 y=0x0.0p+0
+quarter_turn_kernel_at 3fe921fb54442d18 0000000000000000 3fe6a09e667f3bcc 0000000000000000 3fe6a09e667f3bcc 0000000000000000 1 # x=0x1.921fb54442d18p-1 y=0x0.0p+0
+quarter_turn_kernel_above 3fe921fb54442d19 0000000000000000 3fe6a09e667f3bcd 0000000000000000 3fe6a09e667f3bcd 0000000000000000 1 # x=0x1.921fb54442d19p-1 y=0x0.0p+0
+negative_quarter_turn_kernel_below bfe921fb54442d17 0000000000000000 bfe6a09e667f3bcc 0000000000000000 bfe6a09e667f3bcc 0000000000000000 1 # x=-0x1.921fb54442d17p-1 y=0x0.0p+0
+negative_quarter_turn_kernel_at bfe921fb54442d18 0000000000000000 bfe6a09e667f3bcc 0000000000000000 bfe6a09e667f3bcc 0000000000000000 1 # x=-0x1.921fb54442d18p-1 y=0x0.0p+0
+negative_quarter_turn_kernel_above bfe921fb54442d19 0000000000000000 bfe6a09e667f3bcd 0000000000000000 bfe6a09e667f3bcd 0000000000000000 1 # x=-0x1.921fb54442d19p-1 y=0x0.0p+0
+medium_reduction_cutoff_below 413921faffffffff 0000000000000000 bfd4b02e5c25af00 0000000000000000 bfd4b02e5c25af00 0000000000000000 1 # x=0x1.921faffffffffp+20 y=0x0.0p+0
+medium_reduction_cutoff_at 413921fb00000000 0000000000000000 bfd4b02e5be91e9e 0000000000000000 bfd4b02e5be91e9e 0000000000000000 1 # x=0x1.921fb00000000p+20 y=0x0.0p+0
+medium_reduction_cutoff_above 413921fb00000001 0000000000000000 bfd4b02e5bac8e3c 0000000000000000 bfd4b02e5bac8e3c 0000000000000000 1 # x=0x1.921fb00000001p+20 y=0x0.0p+0
+negative_medium_reduction_cutoff_below c13921faffffffff 0000000000000000 3fd4b02e5c25af00 0000000000000000 3fd4b02e5c25af00 0000000000000000 1 # x=-0x1.921faffffffffp+20 y=0x0.0p+0
+negative_medium_reduction_cutoff_at c13921fb00000000 0000000000000000 3fd4b02e5be91e9e 0000000000000000 3fd4b02e5be91e9e 0000000000000000 1 # x=-0x1.921fb00000000p+20 y=0x0.0p+0
+negative_medium_reduction_cutoff_above c13921fb00000001 0000000000000000 3fd4b02e5bac8e3c 0000000000000000 3fd4b02e5bac8e3c 0000000000000000 1 # x=-0x1.921fb00000001p+20 y=0x0.0p+0
+tiny_cutoff_below 3e4fffffffffffff 0000000000000000 3e4fffffffffffff 0000000000000000 3e4fffffffffffff 0000000000000000 1 # x=0x1.fffffffffffffp-27 y=0x0.0p+0
+tiny_cutoff_at 3e50000000000000 0000000000000000 3e50000000000000 0000000000000000 3e50000000000000 0000000000000000 1 # x=0x1.0000000000000p-26 y=0x0.0p+0
+tiny_cutoff_above 3e50000000000001 0000000000000000 3e50000000000001 0000000000000000 3e50000000000001 0000000000000000 1 # x=0x1.0000000000001p-26 y=0x0.0p+0
+negative_tiny_cutoff_below be4fffffffffffff 0000000000000000 be4fffffffffffff 0000000000000000 be4fffffffffffff 0000000000000000 1 # x=-0x1.fffffffffffffp-27 y=0x0.0p+0
+negative_tiny_cutoff_at be50000000000000 0000000000000000 be50000000000000 0000000000000000 be50000000000000 0000000000000000 1 # x=-0x1.0000000000000p-26 y=0x0.0p+0
+negative_tiny_cutoff_above be50000000000001 0000000000000000 be50000000000001 0000000000000000 be50000000000001 0000000000000000 1 # x=-0x1.0000000000001p-26 y=0x0.0p+0

+ 45 - 0
tests/dmath/cases/sincos.txt

@@ -0,0 +1,45 @@
+# dmath_sincos
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep dbfe0e813bed0d5c
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+positive_zero 0000000000000000 0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 1 # x=0x0.0p+0 y=0x0.0p+0
+negative_zero 8000000000000000 0000000000000000 8000000000000000 3ff0000000000000 8000000000000000 3ff0000000000000 1 # x=-0x0.0p+0 y=0x0.0p+0
+least_subnormal 0000000000000001 0000000000000000 0000000000000001 3ff0000000000000 0000000000000001 3ff0000000000000 1 # x=0x0.0000000000001p-1022 y=0x0.0p+0
+negative_least_subnormal 8000000000000001 0000000000000000 8000000000000001 3ff0000000000000 8000000000000001 3ff0000000000000 1 # x=-0x0.0000000000001p-1022 y=0x0.0p+0
+third_subnormal 0000000000000003 0000000000000000 0000000000000003 3ff0000000000000 0000000000000003 3ff0000000000000 1 # x=0x0.0000000000003p-1022 y=0x0.0p+0
+negative_third_subnormal 8000000000000003 0000000000000000 8000000000000003 3ff0000000000000 8000000000000003 3ff0000000000000 1 # x=-0x0.0000000000003p-1022 y=0x0.0p+0
+largest_subnormal 000fffffffffffff 0000000000000000 000fffffffffffff 3ff0000000000000 000fffffffffffff 3ff0000000000000 1 # x=0x0.fffffffffffffp-1022 y=0x0.0p+0
+negative_largest_subnormal 800fffffffffffff 0000000000000000 800fffffffffffff 3ff0000000000000 800fffffffffffff 3ff0000000000000 1 # x=-0x0.fffffffffffffp-1022 y=0x0.0p+0
+least_normal 0010000000000000 0000000000000000 0010000000000000 3ff0000000000000 0010000000000000 3ff0000000000000 1 # x=0x1.0000000000000p-1022 y=0x0.0p+0
+negative_least_normal 8010000000000000 0000000000000000 8010000000000000 3ff0000000000000 8010000000000000 3ff0000000000000 1 # x=-0x1.0000000000000p-1022 y=0x0.0p+0
+largest_finite 7fefffffffffffff 0000000000000000 3f7452fc98b34e97 bfefffe62ecfab75 3f7452fc98b34e97 bfefffe62ecfab75 1 # x=0x1.fffffffffffffp+1023 y=0x0.0p+0
+negative_largest_finite ffefffffffffffff 0000000000000000 bf7452fc98b34e97 bfefffe62ecfab75 bf7452fc98b34e97 bfefffe62ecfab75 1 # x=-0x1.fffffffffffffp+1023 y=0x0.0p+0
+positive_infinity 7ff0000000000000 0000000000000000 nan nan nan nan 1 # x=inf y=0x0.0p+0
+negative_infinity fff0000000000000 0000000000000000 nan nan nan nan 1 # x=-inf y=0x0.0p+0
+quiet_nan_payload 7ff8abcdef135790 0000000000000000 nan nan nan nan 1 # x=nan y=0x0.0p+0
+negative_quiet_nan_payload fff8abcdef135790 0000000000000000 nan nan nan nan 1 # x=nan y=0x0.0p+0
+signaling_nan_payload 7ff0000000010248 0000000000000000 nan nan nan nan 1 # x=nan y=0x0.0p+0
+negative_signaling_nan_payload fff0000000010248 0000000000000000 nan nan nan nan 1 # x=nan y=0x0.0p+0
+small_positive_angle 3fd6000000000000 0000000000000000 3fd591bc9fa2f597 3fee20bf49acd6c1 3fd591bc9fa2f597 3fee20bf49acd6c1 1 # x=0x1.6000000000000p-2 y=0x0.0p+0
+small_negative_angle bfd6000000000000 0000000000000000 bfd591bc9fa2f597 3fee20bf49acd6c1 bfd591bc9fa2f597 3fee20bf49acd6c1 1 # x=-0x1.6000000000000p-2 y=0x0.0p+0
+moderate_positive_angle 4045e80000000000 0000000000000000 bfc5a13747aff14f 3fef8a30fe6ef96c bfc5a13747aff14f 3fef8a30fe6ef96c 1 # x=0x1.5e80000000000p+5 y=0x0.0p+0
+moderate_negative_angle c045e80000000000 0000000000000000 3fc5a13747aff14f 3fef8a30fe6ef96c 3fc5a13747aff14f 3fef8a30fe6ef96c 1 # x=-0x1.5e80000000000p+5 y=0x0.0p+0
+large_reduction 428a5c739b18426f 0000000000000000 3fed341a0bb536bf 3fda2a49d24e0f94 3fed341a0bb536bf 3fda2a49d24e0f94 1 # x=0x1.a5c739b18426fp+41 y=0x0.0p+0
+very_large_reduction 72a73b4a82cf19de 0000000000000000 3fe88f9b8b914182 3fe4832d2f71ebb6 3fe88f9b8b914182 3fe4832d2f71ebb6 1 # x=0x1.73b4a82cf19dep+811 y=0x0.0p+0
+quarter_turn_kernel_below 3fe921fb54442d17 0000000000000000 3fe6a09e667f3bcc 3fe6a09e667f3bce 3fe6a09e667f3bcc 3fe6a09e667f3bcd 1 # x=0x1.921fb54442d17p-1 y=0x0.0p+0
+quarter_turn_kernel_at 3fe921fb54442d18 0000000000000000 3fe6a09e667f3bcc 3fe6a09e667f3bcd 3fe6a09e667f3bcc 3fe6a09e667f3bcd 1 # x=0x1.921fb54442d18p-1 y=0x0.0p+0
+quarter_turn_kernel_above 3fe921fb54442d19 0000000000000000 3fe6a09e667f3bcd 3fe6a09e667f3bcc 3fe6a09e667f3bcd 3fe6a09e667f3bcc 1 # x=0x1.921fb54442d19p-1 y=0x0.0p+0
+negative_quarter_turn_kernel_below bfe921fb54442d17 0000000000000000 bfe6a09e667f3bcc 3fe6a09e667f3bce bfe6a09e667f3bcc 3fe6a09e667f3bcd 1 # x=-0x1.921fb54442d17p-1 y=0x0.0p+0
+negative_quarter_turn_kernel_at bfe921fb54442d18 0000000000000000 bfe6a09e667f3bcc 3fe6a09e667f3bcd bfe6a09e667f3bcc 3fe6a09e667f3bcd 1 # x=-0x1.921fb54442d18p-1 y=0x0.0p+0
+negative_quarter_turn_kernel_above bfe921fb54442d19 0000000000000000 bfe6a09e667f3bcd 3fe6a09e667f3bcc bfe6a09e667f3bcd 3fe6a09e667f3bcc 1 # x=-0x1.921fb54442d19p-1 y=0x0.0p+0
+medium_reduction_cutoff_below 413921faffffffff 0000000000000000 bfd4b02e5c25af00 3fee483125700ac3 bfd4b02e5c25af00 3fee483125700ac3 1 # x=0x1.921faffffffffp+20 y=0x0.0p+0
+medium_reduction_cutoff_at 413921fb00000000 0000000000000000 bfd4b02e5be91e9e 3fee4831257a62da bfd4b02e5be91e9e 3fee4831257a62da 1 # x=0x1.921fb00000000p+20 y=0x0.0p+0
+medium_reduction_cutoff_above 413921fb00000001 0000000000000000 bfd4b02e5bac8e3c 3fee48312584baf1 bfd4b02e5bac8e3c 3fee48312584baf1 1 # x=0x1.921fb00000001p+20 y=0x0.0p+0
+negative_medium_reduction_cutoff_below c13921faffffffff 0000000000000000 3fd4b02e5c25af00 3fee483125700ac3 3fd4b02e5c25af00 3fee483125700ac3 1 # x=-0x1.921faffffffffp+20 y=0x0.0p+0
+negative_medium_reduction_cutoff_at c13921fb00000000 0000000000000000 3fd4b02e5be91e9e 3fee4831257a62da 3fd4b02e5be91e9e 3fee4831257a62da 1 # x=-0x1.921fb00000000p+20 y=0x0.0p+0
+negative_medium_reduction_cutoff_above c13921fb00000001 0000000000000000 3fd4b02e5bac8e3c 3fee48312584baf1 3fd4b02e5bac8e3c 3fee48312584baf1 1 # x=-0x1.921fb00000001p+20 y=0x0.0p+0
+second_quadrant 4002800000000000 0000000000000000 3fe7981d6e5b8b11 bfe59e10a28e82ed 3fe7981d6e5b8b11 bfe59e10a28e82ed 1 # x=0x1.2800000000000p+1 y=0x0.0p+0
+third_quadrant 4010c00000000000 0000000000000000 bfebb13084c06416 bfe009266130831c bfebb13084c06416 bfe009266130831c 1 # x=0x1.0c00000000000p+2 y=0x0.0p+0
+fourth_quadrant 4017c00000000000 0000000000000000 bfd5af945b89d004 3fee1b63c00b78fb bfd5af945b89d004 3fee1b63c00b78fb 1 # x=0x1.7c00000000000p+2 y=0x0.0p+0

+ 33 - 0
tests/dmath/cases/sqrt.txt

@@ -0,0 +1,33 @@
+# dmath_sqrt
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep f6401f137a0d9229
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+positive_zero 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.0p+0 y=0x0.0p+0
+negative_zero 8000000000000000 0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x0.0p+0 y=0x0.0p+0
+least_subnormal 0000000000000001 0000000000000000 1e60000000000000 0000000000000000 1e60000000000000 0000000000000000 0 # x=0x0.0000000000001p-1022 y=0x0.0p+0
+negative_least_subnormal 8000000000000001 0000000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=-0x0.0000000000001p-1022 y=0x0.0p+0
+third_subnormal 0000000000000003 0000000000000000 1e6bb67ae8584caa 0000000000000000 1e6bb67ae8584caa 0000000000000000 0 # x=0x0.0000000000003p-1022 y=0x0.0p+0
+negative_third_subnormal 8000000000000003 0000000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=-0x0.0000000000003p-1022 y=0x0.0p+0
+largest_subnormal 000fffffffffffff 0000000000000000 1fffffffffffffff 0000000000000000 1fffffffffffffff 0000000000000000 0 # x=0x0.fffffffffffffp-1022 y=0x0.0p+0
+negative_largest_subnormal 800fffffffffffff 0000000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=-0x0.fffffffffffffp-1022 y=0x0.0p+0
+least_normal 0010000000000000 0000000000000000 2000000000000000 0000000000000000 2000000000000000 0000000000000000 0 # x=0x1.0000000000000p-1022 y=0x0.0p+0
+negative_least_normal 8010000000000000 0000000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=-0x1.0000000000000p-1022 y=0x0.0p+0
+largest_finite 7fefffffffffffff 0000000000000000 5fefffffffffffff 0000000000000000 5fefffffffffffff 0000000000000000 0 # x=0x1.fffffffffffffp+1023 y=0x0.0p+0
+negative_largest_finite ffefffffffffffff 0000000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=-0x1.fffffffffffffp+1023 y=0x0.0p+0
+positive_infinity 7ff0000000000000 0000000000000000 +inf 0000000000000000 +inf 0000000000000000 0 # x=inf y=0x0.0p+0
+negative_infinity fff0000000000000 0000000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=-inf y=0x0.0p+0
+quiet_nan_payload 7ff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=0x0.0p+0
+negative_quiet_nan_payload fff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=0x0.0p+0
+signaling_nan_payload 7ff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=0x0.0p+0
+negative_signaling_nan_payload fff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=0x0.0p+0
+exact_square 4069d48000000000 0000000000000000 402cc00000000000 0000000000000000 402cc00000000000 0000000000000000 0 # x=0x1.9d48000000000p+7 y=0x0.0p+0
+irrational 402b400000000000 0000000000000000 400d8796e35ddbb2 0000000000000000 400d8796e35ddbb2 0000000000000000 0 # x=0x1.b400000000000p+3 y=0x0.0p+0
+wide_significand 598a5c739b18426f 0000000000000000 4cbd0b466b13b005 0000000000000000 4cbd0b466b13b005 0000000000000000 0 # x=0x1.a5c739b18426fp+409 y=0x0.0p+0
+square_neighbor_below 4069d47fffffffff 0000000000000000 402cbfffffffffff 0000000000000000 402cbfffffffffff 0000000000000000 0 # x=0x1.9d47fffffffffp+7 y=0x0.0p+0
+square_neighbor_at 4069d48000000000 0000000000000000 402cc00000000000 0000000000000000 402cc00000000000 0000000000000000 0 # x=0x1.9d48000000000p+7 y=0x0.0p+0
+square_neighbor_above 4069d48000000001 0000000000000000 402cc00000000001 0000000000000000 402cc00000000001 0000000000000000 0 # x=0x1.9d48000000001p+7 y=0x0.0p+0
+normal_subnormal_transition_below 000fffffffffffff 0000000000000000 1fffffffffffffff 0000000000000000 1fffffffffffffff 0000000000000000 0 # x=0x0.fffffffffffffp-1022 y=0x0.0p+0
+normal_subnormal_transition_at 0010000000000000 0000000000000000 2000000000000000 0000000000000000 2000000000000000 0000000000000000 0 # x=0x1.0000000000000p-1022 y=0x0.0p+0
+normal_subnormal_transition_above 0010000000000001 0000000000000000 2000000000000000 0000000000000000 2000000000000000 0000000000000000 0 # x=0x1.0000000000001p-1022 y=0x0.0p+0

+ 54 - 0
tests/dmath/cases/tan.txt

@@ -0,0 +1,54 @@
+# dmath_tan
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep 536e28a9034f3f2d
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+positive_zero 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 1 # x=0x0.0p+0 y=0x0.0p+0
+negative_zero 8000000000000000 0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 1 # x=-0x0.0p+0 y=0x0.0p+0
+least_subnormal 0000000000000001 0000000000000000 0000000000000001 0000000000000000 0000000000000001 0000000000000000 1 # x=0x0.0000000000001p-1022 y=0x0.0p+0
+negative_least_subnormal 8000000000000001 0000000000000000 8000000000000001 0000000000000000 8000000000000001 0000000000000000 1 # x=-0x0.0000000000001p-1022 y=0x0.0p+0
+third_subnormal 0000000000000003 0000000000000000 0000000000000003 0000000000000000 0000000000000003 0000000000000000 1 # x=0x0.0000000000003p-1022 y=0x0.0p+0
+negative_third_subnormal 8000000000000003 0000000000000000 8000000000000003 0000000000000000 8000000000000003 0000000000000000 1 # x=-0x0.0000000000003p-1022 y=0x0.0p+0
+largest_subnormal 000fffffffffffff 0000000000000000 000fffffffffffff 0000000000000000 000fffffffffffff 0000000000000000 1 # x=0x0.fffffffffffffp-1022 y=0x0.0p+0
+negative_largest_subnormal 800fffffffffffff 0000000000000000 800fffffffffffff 0000000000000000 800fffffffffffff 0000000000000000 1 # x=-0x0.fffffffffffffp-1022 y=0x0.0p+0
+least_normal 0010000000000000 0000000000000000 0010000000000000 0000000000000000 0010000000000000 0000000000000000 1 # x=0x1.0000000000000p-1022 y=0x0.0p+0
+negative_least_normal 8010000000000000 0000000000000000 8010000000000000 0000000000000000 8010000000000000 0000000000000000 1 # x=-0x1.0000000000000p-1022 y=0x0.0p+0
+largest_finite 7fefffffffffffff 0000000000000000 bf74530cfe729484 0000000000000000 bf74530cfe729484 0000000000000000 1 # x=0x1.fffffffffffffp+1023 y=0x0.0p+0
+negative_largest_finite ffefffffffffffff 0000000000000000 3f74530cfe729484 0000000000000000 3f74530cfe729484 0000000000000000 1 # x=-0x1.fffffffffffffp+1023 y=0x0.0p+0
+positive_infinity 7ff0000000000000 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=inf y=0x0.0p+0
+negative_infinity fff0000000000000 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=-inf y=0x0.0p+0
+quiet_nan_payload 7ff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+negative_quiet_nan_payload fff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+signaling_nan_payload 7ff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+negative_signaling_nan_payload fff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 1 # x=nan y=0x0.0p+0
+small_positive_angle 3fd6000000000000 0000000000000000 3fd6e8d85a6493e1 0000000000000000 3fd6e8d85a6493e1 0000000000000000 1 # x=0x1.6000000000000p-2 y=0x0.0p+0
+small_negative_angle bfd6000000000000 0000000000000000 bfd6e8d85a6493e1 0000000000000000 bfd6e8d85a6493e1 0000000000000000 1 # x=-0x1.6000000000000p-2 y=0x0.0p+0
+moderate_positive_angle 4045e80000000000 0000000000000000 bfc5f20215e0709b 0000000000000000 bfc5f20215e0709b 0000000000000000 1 # x=0x1.5e80000000000p+5 y=0x0.0p+0
+moderate_negative_angle c045e80000000000 0000000000000000 3fc5f20215e0709b 0000000000000000 3fc5f20215e0709b 0000000000000000 1 # x=-0x1.5e80000000000p+5 y=0x0.0p+0
+large_reduction 428a5c739b18426f 0000000000000000 4001dba1eaffde8c 0000000000000000 4001dba1eaffde8c 0000000000000000 1 # x=0x1.a5c739b18426fp+41 y=0x0.0p+0
+very_large_reduction 72a73b4a82cf19de 0000000000000000 3ff3286eb86a39ad 0000000000000000 3ff3286eb86a39ad 0000000000000000 1 # x=0x1.73b4a82cf19dep+811 y=0x0.0p+0
+quarter_turn_kernel_below 3fe921fb54442d17 0000000000000000 3feffffffffffffd 0000000000000000 3feffffffffffffd 0000000000000000 1 # x=0x1.921fb54442d17p-1 y=0x0.0p+0
+quarter_turn_kernel_at 3fe921fb54442d18 0000000000000000 3fefffffffffffff 0000000000000000 3fefffffffffffff 0000000000000000 1 # x=0x1.921fb54442d18p-1 y=0x0.0p+0
+quarter_turn_kernel_above 3fe921fb54442d19 0000000000000000 3ff0000000000001 0000000000000000 3ff0000000000001 0000000000000000 1 # x=0x1.921fb54442d19p-1 y=0x0.0p+0
+negative_quarter_turn_kernel_below bfe921fb54442d17 0000000000000000 bfeffffffffffffd 0000000000000000 bfeffffffffffffd 0000000000000000 1 # x=-0x1.921fb54442d17p-1 y=0x0.0p+0
+negative_quarter_turn_kernel_at bfe921fb54442d18 0000000000000000 bfefffffffffffff 0000000000000000 bfefffffffffffff 0000000000000000 1 # x=-0x1.921fb54442d18p-1 y=0x0.0p+0
+negative_quarter_turn_kernel_above bfe921fb54442d19 0000000000000000 bff0000000000001 0000000000000000 bff0000000000001 0000000000000000 1 # x=-0x1.921fb54442d19p-1 y=0x0.0p+0
+medium_reduction_cutoff_below 413921faffffffff 0000000000000000 bfd5dca6bd5e8435 0000000000000000 bfd5dca6bd5e8435 0000000000000000 1 # x=0x1.921faffffffffp+20 y=0x0.0p+0
+medium_reduction_cutoff_at 413921fb00000000 0000000000000000 bfd5dca6bd170c6f 0000000000000000 bfd5dca6bd170c6f 0000000000000000 1 # x=0x1.921fb00000000p+20 y=0x0.0p+0
+medium_reduction_cutoff_above 413921fb00000001 0000000000000000 bfd5dca6bccf94a9 0000000000000000 bfd5dca6bccf94a8 0000000000000000 1 # x=0x1.921fb00000001p+20 y=0x0.0p+0
+negative_medium_reduction_cutoff_below c13921faffffffff 0000000000000000 3fd5dca6bd5e8435 0000000000000000 3fd5dca6bd5e8435 0000000000000000 1 # x=-0x1.921faffffffffp+20 y=0x0.0p+0
+negative_medium_reduction_cutoff_at c13921fb00000000 0000000000000000 3fd5dca6bd170c6f 0000000000000000 3fd5dca6bd170c6f 0000000000000000 1 # x=-0x1.921fb00000000p+20 y=0x0.0p+0
+negative_medium_reduction_cutoff_above c13921fb00000001 0000000000000000 3fd5dca6bccf94a9 0000000000000000 3fd5dca6bccf94a8 0000000000000000 1 # x=-0x1.921fb00000001p+20 y=0x0.0p+0
+reciprocal_pole_below 4012d97c7f3321d1 0000000000000000 430a8410087262e4 0000000000000000 430a8410087262e4 0000000000000000 1 # x=0x1.2d97c7f3321d1p+2 y=0x0.0p+0
+reciprocal_pole_at 4012d97c7f3321d2 0000000000000000 4333570efd768923 0000000000000000 4333570efd768923 0000000000000000 1 # x=0x1.2d97c7f3321d2p+2 y=0x0.0p+0
+reciprocal_pole_above 4012d97c7f3321d3 0000000000000000 c3142c0d64d5de51 0000000000000000 c3142c0d64d5de51 0000000000000000 1 # x=0x1.2d97c7f3321d3p+2 y=0x0.0p+0
+negative_reciprocal_pole_below c012d97c7f3321d1 0000000000000000 c30a8410087262e4 0000000000000000 c30a8410087262e4 0000000000000000 1 # x=-0x1.2d97c7f3321d1p+2 y=0x0.0p+0
+negative_reciprocal_pole_at c012d97c7f3321d2 0000000000000000 c333570efd768923 0000000000000000 c333570efd768923 0000000000000000 1 # x=-0x1.2d97c7f3321d2p+2 y=0x0.0p+0
+negative_reciprocal_pole_above c012d97c7f3321d3 0000000000000000 43142c0d64d5de51 0000000000000000 43142c0d64d5de51 0000000000000000 1 # x=-0x1.2d97c7f3321d3p+2 y=0x0.0p+0
+kernel_transform_below 3fe59427ffffffff 0000000000000000 3fe99427887a14d4 0000000000000000 3fe99427887a14d4 0000000000000000 1 # x=0x1.59427ffffffffp-1 y=0x0.0p+0
+kernel_transform_at 3fe5942800000000 0000000000000000 3fe99427887a14d6 0000000000000000 3fe99427887a14d6 0000000000000000 1 # x=0x1.5942800000000p-1 y=0x0.0p+0
+kernel_transform_above 3fe5942800000001 0000000000000000 3fe99427887a14d8 0000000000000000 3fe99427887a14d8 0000000000000000 1 # x=0x1.5942800000001p-1 y=0x0.0p+0
+negative_kernel_transform_below bfe59427ffffffff 0000000000000000 bfe99427887a14d4 0000000000000000 bfe99427887a14d4 0000000000000000 1 # x=-0x1.59427ffffffffp-1 y=0x0.0p+0
+negative_kernel_transform_at bfe5942800000000 0000000000000000 bfe99427887a14d6 0000000000000000 bfe99427887a14d6 0000000000000000 1 # x=-0x1.5942800000000p-1 y=0x0.0p+0
+negative_kernel_transform_above bfe5942800000001 0000000000000000 bfe99427887a14d8 0000000000000000 bfe99427887a14d8 0000000000000000 1 # x=-0x1.5942800000001p-1 y=0x0.0p+0

+ 68 - 0
tests/dmath/cases/trunc.txt

@@ -0,0 +1,68 @@
+# dmath_trunc
+# Independent oracle: Decimal at 430 and 570 digits / exact Fraction arithmetic.
+# Frozen bits and sweep require review; generation never recalibrates them.
+# Nonfinite outputs: nan checks classification; +/-inf checks classification and sign.
+# sweep c3939beaf1fc7396
+# case  input0  input1  frozen0  frozen1  reference0  reference1  max_ulp
+positive_zero 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.0p+0 y=0x0.0p+0
+negative_zero 8000000000000000 0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x0.0p+0 y=0x0.0p+0
+least_subnormal 0000000000000001 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.0000000000001p-1022 y=0x0.0p+0
+negative_least_subnormal 8000000000000001 0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x0.0000000000001p-1022 y=0x0.0p+0
+third_subnormal 0000000000000003 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.0000000000003p-1022 y=0x0.0p+0
+negative_third_subnormal 8000000000000003 0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x0.0000000000003p-1022 y=0x0.0p+0
+largest_subnormal 000fffffffffffff 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x0.fffffffffffffp-1022 y=0x0.0p+0
+negative_largest_subnormal 800fffffffffffff 0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x0.fffffffffffffp-1022 y=0x0.0p+0
+least_normal 0010000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x1.0000000000000p-1022 y=0x0.0p+0
+negative_least_normal 8010000000000000 0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x1.0000000000000p-1022 y=0x0.0p+0
+largest_finite 7fefffffffffffff 0000000000000000 7fefffffffffffff 0000000000000000 7fefffffffffffff 0000000000000000 0 # x=0x1.fffffffffffffp+1023 y=0x0.0p+0
+negative_largest_finite ffefffffffffffff 0000000000000000 ffefffffffffffff 0000000000000000 ffefffffffffffff 0000000000000000 0 # x=-0x1.fffffffffffffp+1023 y=0x0.0p+0
+positive_infinity 7ff0000000000000 0000000000000000 +inf 0000000000000000 +inf 0000000000000000 0 # x=inf y=0x0.0p+0
+negative_infinity fff0000000000000 0000000000000000 -inf 0000000000000000 -inf 0000000000000000 0 # x=-inf y=0x0.0p+0
+quiet_nan_payload 7ff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=0x0.0p+0
+negative_quiet_nan_payload fff8abcdef135790 0000000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=0x0.0p+0
+signaling_nan_payload 7ff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=0x0.0p+0
+negative_signaling_nan_payload fff0000000010248 0000000000000000 nan 0000000000000000 nan 0000000000000000 0 # x=nan y=0x0.0p+0
+unit_below 3fefffffffffffff 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x1.fffffffffffffp-1 y=0x0.0p+0
+unit_at 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 0 # x=0x1.0000000000000p+0 y=0x0.0p+0
+unit_above 3ff0000000000001 0000000000000000 3ff0000000000000 0000000000000000 3ff0000000000000 0000000000000000 0 # x=0x1.0000000000001p+0 y=0x0.0p+0
+negative_unit_below bfefffffffffffff 0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x1.fffffffffffffp-1 y=0x0.0p+0
+negative_unit_at bff0000000000000 0000000000000000 bff0000000000000 0000000000000000 bff0000000000000 0000000000000000 0 # x=-0x1.0000000000000p+0 y=0x0.0p+0
+negative_unit_above bff0000000000001 0000000000000000 bff0000000000000 0000000000000000 bff0000000000000 0000000000000000 0 # x=-0x1.0000000000001p+0 y=0x0.0p+0
+half_below 3fdfffffffffffff 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x1.fffffffffffffp-2 y=0x0.0p+0
+half_at 3fe0000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x1.0000000000000p-1 y=0x0.0p+0
+half_above 3fe0000000000001 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0 # x=0x1.0000000000001p-1 y=0x0.0p+0
+negative_half_below bfdfffffffffffff 0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x1.fffffffffffffp-2 y=0x0.0p+0
+negative_half_at bfe0000000000000 0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x1.0000000000000p-1 y=0x0.0p+0
+negative_half_above bfe0000000000001 0000000000000000 8000000000000000 0000000000000000 8000000000000000 0000000000000000 0 # x=-0x1.0000000000001p-1 y=0x0.0p+0
+word_split_below 412fffffffffffff 0000000000000000 412ffffe00000000 0000000000000000 412ffffe00000000 0000000000000000 0 # x=0x1.fffffffffffffp+19 y=0x0.0p+0
+word_split_at 4130000000000000 0000000000000000 4130000000000000 0000000000000000 4130000000000000 0000000000000000 0 # x=0x1.0000000000000p+20 y=0x0.0p+0
+word_split_above 4130000000000001 0000000000000000 4130000000000000 0000000000000000 4130000000000000 0000000000000000 0 # x=0x1.0000000000001p+20 y=0x0.0p+0
+negative_word_split_below c12fffffffffffff 0000000000000000 c12ffffe00000000 0000000000000000 c12ffffe00000000 0000000000000000 0 # x=-0x1.fffffffffffffp+19 y=0x0.0p+0
+negative_word_split_at c130000000000000 0000000000000000 c130000000000000 0000000000000000 c130000000000000 0000000000000000 0 # x=-0x1.0000000000000p+20 y=0x0.0p+0
+negative_word_split_above c130000000000001 0000000000000000 c130000000000000 0000000000000000 c130000000000000 0000000000000000 0 # x=-0x1.0000000000001p+20 y=0x0.0p+0
+signed32_below 41dfffffffffffff 0000000000000000 41dfffffffc00000 0000000000000000 41dfffffffc00000 0000000000000000 0 # x=0x1.fffffffffffffp+30 y=0x0.0p+0
+signed32_at 41e0000000000000 0000000000000000 41e0000000000000 0000000000000000 41e0000000000000 0000000000000000 0 # x=0x1.0000000000000p+31 y=0x0.0p+0
+signed32_above 41e0000000000001 0000000000000000 41e0000000000000 0000000000000000 41e0000000000000 0000000000000000 0 # x=0x1.0000000000001p+31 y=0x0.0p+0
+negative_signed32_below c1dfffffffffffff 0000000000000000 c1dfffffffc00000 0000000000000000 c1dfffffffc00000 0000000000000000 0 # x=-0x1.fffffffffffffp+30 y=0x0.0p+0
+negative_signed32_at c1e0000000000000 0000000000000000 c1e0000000000000 0000000000000000 c1e0000000000000 0000000000000000 0 # x=-0x1.0000000000000p+31 y=0x0.0p+0
+negative_signed32_above c1e0000000000001 0000000000000000 c1e0000000000000 0000000000000000 c1e0000000000000 0000000000000000 0 # x=-0x1.0000000000001p+31 y=0x0.0p+0
+last_fractional_binade_below 431fffffffffffff 0000000000000000 431ffffffffffffc 0000000000000000 431ffffffffffffc 0000000000000000 0 # x=0x1.fffffffffffffp+50 y=0x0.0p+0
+last_fractional_binade_at 4320000000000000 0000000000000000 4320000000000000 0000000000000000 4320000000000000 0000000000000000 0 # x=0x1.0000000000000p+51 y=0x0.0p+0
+last_fractional_binade_above 4320000000000001 0000000000000000 4320000000000000 0000000000000000 4320000000000000 0000000000000000 0 # x=0x1.0000000000001p+51 y=0x0.0p+0
+negative_last_fractional_binade_below c31fffffffffffff 0000000000000000 c31ffffffffffffc 0000000000000000 c31ffffffffffffc 0000000000000000 0 # x=-0x1.fffffffffffffp+50 y=0x0.0p+0
+negative_last_fractional_binade_at c320000000000000 0000000000000000 c320000000000000 0000000000000000 c320000000000000 0000000000000000 0 # x=-0x1.0000000000000p+51 y=0x0.0p+0
+negative_last_fractional_binade_above c320000000000001 0000000000000000 c320000000000000 0000000000000000 c320000000000000 0000000000000000 0 # x=-0x1.0000000000001p+51 y=0x0.0p+0
+integral_binade_below 432fffffffffffff 0000000000000000 432ffffffffffffe 0000000000000000 432ffffffffffffe 0000000000000000 0 # x=0x1.fffffffffffffp+51 y=0x0.0p+0
+integral_binade_at 4330000000000000 0000000000000000 4330000000000000 0000000000000000 4330000000000000 0000000000000000 0 # x=0x1.0000000000000p+52 y=0x0.0p+0
+integral_binade_above 4330000000000001 0000000000000000 4330000000000001 0000000000000000 4330000000000001 0000000000000000 0 # x=0x1.0000000000001p+52 y=0x0.0p+0
+negative_integral_binade_below c32fffffffffffff 0000000000000000 c32ffffffffffffe 0000000000000000 c32ffffffffffffe 0000000000000000 0 # x=-0x1.fffffffffffffp+51 y=0x0.0p+0
+negative_integral_binade_at c330000000000000 0000000000000000 c330000000000000 0000000000000000 c330000000000000 0000000000000000 0 # x=-0x1.0000000000000p+52 y=0x0.0p+0
+negative_integral_binade_above c330000000000001 0000000000000000 c330000000000001 0000000000000000 c330000000000001 0000000000000000 0 # x=-0x1.0000000000001p+52 y=0x0.0p+0
+signed64_below 43dfffffffffffff 0000000000000000 43dfffffffffffff 0000000000000000 43dfffffffffffff 0000000000000000 0 # x=0x1.fffffffffffffp+62 y=0x0.0p+0
+signed64_at 43e0000000000000 0000000000000000 43e0000000000000 0000000000000000 43e0000000000000 0000000000000000 0 # x=0x1.0000000000000p+63 y=0x0.0p+0
+signed64_above 43e0000000000001 0000000000000000 43e0000000000001 0000000000000000 43e0000000000001 0000000000000000 0 # x=0x1.0000000000001p+63 y=0x0.0p+0
+negative_signed64_below c3dfffffffffffff 0000000000000000 c3dfffffffffffff 0000000000000000 c3dfffffffffffff 0000000000000000 0 # x=-0x1.fffffffffffffp+62 y=0x0.0p+0
+negative_signed64_at c3e0000000000000 0000000000000000 c3e0000000000000 0000000000000000 c3e0000000000000 0000000000000000 0 # x=-0x1.0000000000000p+63 y=0x0.0p+0
+negative_signed64_above c3e0000000000001 0000000000000000 c3e0000000000001 0000000000000000 c3e0000000000001 0000000000000000 0 # x=-0x1.0000000000001p+63 y=0x0.0p+0
+drop_positive_fraction 4042d80000000000 0000000000000000 4042800000000000 0000000000000000 4042800000000000 0000000000000000 0 # x=0x1.2d80000000000p+5 y=0x0.0p+0
+drop_negative_fraction c042d80000000000 0000000000000000 c042800000000000 0000000000000000 c042800000000000 0000000000000000 0 # x=-0x1.2d80000000000p+5 y=0x0.0p+0