Skip to content

proven_c_lib-v0.4.0

Choose a tag to compare

@rubidus-api rubidus-api released this 30 Sep 14:34
· 34 commits to main since this release

A MINOR release: nothing public removed. The whole test suite now runs natively on Windows
(./nob build -no-run, a mingw-w64 build for x86-64 and i686), and its first run found six
Windows defects, all fixed - an empty directory could not be removed, pread/pwrite moved the file
position, positioned calls on a pipe were not refused, and the end of a pipe read as an I/O error
(B-035). Float parsing is faster than glibc at every length measured (B-043), and 32-bit targets
use the Eisel-Lemire fast path (B-042). MSVC and clang-cl are stated as not supported. Behaviour
changes only where it was wrong: proven_fs_remove on an empty directory on Windows, and the
Windows pipe and position cases above.

Added

  • The full test suite runs on Windows (B-035). ./nob build -no-run builds every test
    executable and runs none; the build driver asks the compiler for its target, so a mingw-w64
    cross compiler produces static .exe tests (with -lbcrypt, without -ldl).
    win11kd-full-suite.sh and win11kd-run-suite.ps1 build both word sizes and
    run them natively, reporting PASS / FAIL / SKIP / TIMEOUT per test. First run on the Windows 11
    test VM found the six defects below. Three tests that skipped on Windows now run there
    (test_unit_sysio_streams, test_regression_scanner_short_read,
    test_regression_scanner_float_split). x86-64 and i686 each pass 214 with 0 failures; 7
    fixtures whose subject is POSIX skip.

Changed

  • Float parsing is faster than glibc at every length measured (B-043). Three changes, each
    exact: a direct Eisel-Lemire layer (Lemire 2021) proves most results from a 64x128-bit product
    with a truncated power of five, where the staged layer validated every candidate with big-
    integer arithmetic; a significand past 19 digits is bounded by its first 19 digits and the same
    plus one, instead of going to the exact path; and one pass reads the digits, where a digit-by-
    digit builder kept pending-zero bookkeeping. test_bench_float_host, x86-64, against glibc
    strtod: %.6g 83 -> 81 ns (0.58x), ~16 digits 186 -> 145 ns (0.72x), %.17g 224 -> 152 ns
    (0.75x, was 1.13x), 25 digits ~640 -> 197 ns (0.86x, a new corpus). Results are unchanged:
    every row is checked against strtod in the same run, and 60 million generated inputs - random
    significands and exponents, %.15g-%.40g of random doubles, integers above 2^53, subnormal
    and overflow edges - matched strtod bit for bit, with and without 128-bit integers. The
    cached powers come from scripts/generate_float_decimal_tables.py, which checks its exponent
    estimate against exact integer arithmetic.
  • The Eisel-Lemire float-parsing fast path is used on 32-bit targets too (B-042). It was
    compiled only where the compiler has unsigned __int128, although the code needs none - it
    goes through the portable 64x64 multiply. Without it a 32-bit target sent every decimal past
    the Clinger path to the exact big-integer path. Measured with 128-bit integers disabled on
    x86-64 (test_bench_float_host, release): 16-digit parsing 287 -> 183 ns, 17-digit 473 -> 222 ns;
    the results are checked against the host strtod in the same run, and the Windows i686 run
    passes the differential corpora and expects the fast path in test_unit_float_parse_api.
  • MSVC and clang-cl are not supported (owner decision; possibly later). Their C23 support is
    incomplete. The manual used to say recent MSVC worked, which was never verified; it now names
    what is: GCC 13+, Clang 16+, and on Windows mingw-w64 GCC (x86-64 and i686).

Fixed

  • Windows: proven_fs_remove deletes an empty directory, as POSIX remove() does. It called
    DeleteFileW only, which refuses a directory, and reported PERMISSION.
  • Windows: proven_fs_pread and proven_fs_pwrite no longer move the file position. A
    positioned ReadFile/WriteFile on a synchronous handle leaves the pointer after the bytes;
    the position is now restored.
  • Windows: positioned calls on a pipe are UNSUPPORTED. proven_fs_seek, pread and pwrite
    used SetFilePointerEx / an OVERLAPPED offset on a pipe, which Windows does not support, and
    proven_sysio_scan_chunk therefore accepted a pipe it must refuse. The handle type is now
    checked first (FILE_TYPE_DISK), matching POSIX ESPIPE.
  • Windows: the end of a pipe is EOF. ReadFile reports a closed writer as ERROR_BROKEN_PIPE,
    which came back as PROVEN_ERR_IO - so producer | program ended in an error. Both read paths
    now map it to PROVEN_ERR_EOF, as read(2) returning 0 does.
  • Tests and examples that assumed POSIX or a 64-bit target. Permission checks compare with the
    mode read back after chmod (Windows keeps only the owner-write bit); the durable-write example
    accepts sync_dir's documented UNSUPPORTED on Windows; test_unit_u128_mul and
    test_unit_float_bigint_divmod have references without __int128; a float comparison
    uses a stored double, not a literal that x87 evaluates in long double; a fixture no longer
    needs a build/ directory.
  • scripts/release.sh builds a release's PDFs with one date. The site is built at the release
    commit and again by --publish at the site commit; both now take the date of the commit that
    last set the version, so the uploaded PDFs equal the committed ones without a re-publish.