Skip to content

Add optional no-stdlib mode#62

Open
MitchellThompkins wants to merge 5 commits into
kthohr:masterfrom
MitchellThompkins:add-optional-no-stdlib
Open

Add optional no-stdlib mode#62
MitchellThompkins wants to merge 5 commits into
kthohr:masterfrom
MitchellThompkins:add-optional-no-stdlib

Conversation

@MitchellThompkins
Copy link
Copy Markdown

Add optional no-stdlib (builtin traits) mode

Summary

This adds an completely opt-in -nostdlib compliant variant of gcem. That is; it adds a variant that does not require stdlib support.

There are some freestanding/bare-metal platforms, almost entirely embedded, that build without stdlib support. Today gcem relies on <utility>, <type_traits>, and <limits> which makes it impossible to use in those environments. This library is really powerful for those platforms b/c you can offload a lot of math into the compiler. I worked on consteig which is targeted largely towards those environments and specifically had to write all of the constexpr math functions from scratch instead of using this library (although the change this PR introduces would allow me to use this dependency in MitchellThompkins/consteig#62).

Again, the default behavior is unchanged so existing users see no difference.

Note that this PR builds on these two:

  1. issue 59: Fix decade boundary detection in find_exponent and mantissa for long double #60
  2. Dockerize CI to pin compiler dependencies and fix coverage pipeline #61

(1) is a good fix I think, and (2) is a necessary fix in order to make this testing consistent.

Modes

Selected by defining one of the following before including gcem.hpp:

Mode Behavior
(default) Uses <utility>, <type_traits>, <limits> from the hosted stdlib. Same as today.
GCEM_TRAITS_BUILTIN Self-contained implementation using __builtin_* intrinsics and compiler-predefined macros. Requires GCC or Clang. Should work with modern MSVC (but I've never seen MSVC compiled freestanding).
GCEM_TRAITS_CUSTOM Skips all definitions; user supplies their own in namespace gcem. Provides an alternative for unusual or proprietary toolchains (like IAR).

stdlib stand-in changes

  • include/gcem_incl/gcem_type_traits.hpp: enable_if, is_integral, is_signed, conditional, common_type, plus the supporting remove_reference / remove_cv / decay.
  • include/gcem_incl/gcem_limits.hpp: gcem_limits<T> for float, double, long double (via __builtin_huge_val* / __builtin_nan* / __FLT_*__ macros), and for every fundamental integer type that is_integral accepts: bool, char, signed/unsigned char, short/unsigned short, int/unsigned int, long/unsigned long, long long/unsigned long long. This means <cstdint> typedefs (uint8_t, int16_t, size_t, etc.) all resolve via the existing fundamental-type specializations so there is no extra work needed at call sites.
  • include/gcem_incl/gcem_utility.hpp: declval for use in common_type's unevaluated context.

Each replacement carries a permalink back to the corresponding line in libstdc++ (pinned to a specific gcc-mirror commit) so reviewers and future maintainers can verify behavior matches std semantics. I tried my best to match these up.

gcem internal changes

  • gcem_options.hpp no longer includes <cstddef>, <limits>, or <type_traits> directly. Instead it pulls in the new headers, which dispatch to stdlib or builtins based on mode.
  • Call sites that referenced std::is_integral, std::enable_if, std::is_signed, std::numeric_limits, etc. now use the unqualified gcem:: versions: binomial_coef.hpp, factorial.hpp, gcd.hpp, log.hpp, pow.hpp, pow_integral.hpp. In default mode these are using aliases for the std versions, so the behavior is identical.
  • GCLIM<T> is now gcem::gcem_limits<T> instead of std::numeric_limits<T>.

CI changes

  • Linux and macOS jobs each gained a second test step that runs the suite with GCEM_TRAITS_FLAGS="-DGCEM_TRAITS_BUILTIN". The builtin step is skipped for Coverage builds to avoid clobbering coverage data.
  • tests/Makefile forwards GCEM_TRAITS_FLAGS to the compiler.
  • run-local-ci.sh mirrors the CI matrix so both modes can be exercised locally.

being that they are always locked-down so they don't rot. Also adds
weekly pipelines to run and adds a workflow for running tests in the
container locally.

Modify workflow for maintaining docker image

modify coverage workflow and dockerfile to support that

publish new docker image

attempt to derive coverage from specified gcov version

manually assign CC?

missing curl

update container with curl

I think codecov v5 requires repo secrects

support c++23 while I am at it

update container to support c++23 tests

do what logs say

test more macos versions

this file does not buy us anything

this should fail CI correctly now

Revert "this should fail CI correctly now"

This reverts commit 00cbd4c.
slightly larger than the corresponding long double values 0.1L and
0.001L (which was prevoiusly used). This caused find_exponent to return
the wrong exponent for those exact boundary values, e.g. log(0.1L)
returned 2*ln(0.1).

This actually effected all calls to gcem::log; it just only manifests
when log lands exactly on 0.1 or 0.001 in long double.

add test case for failing log case

add 8 epsilon of error

add tests for find_exponent

make epsilon ULP choice configurable and add mantissa.hpp tests

no reason to use T(8)

wording updates

fix fall-through for 10.0L and 100.0L
GCEM_TRAITS_BUILTIN for freestanding/bare-metal targets and
GCEM_TRAITS_CUSTOM for user-supplied definitions. Default behavior is
unchanged. Adds gcem_utility.hpp, gcem_type_traits.hpp, and
gcem_limits.hpp as self-contained replacements for <utility>,
<type_traits>, and <limits>.  CI matrix doubled to exercise both stdlib
and builtin paths.
@MitchellThompkins
Copy link
Copy Markdown
Author

I have a sister-PR over in my fork with passing tests: https://github.com/MitchellThompkins/gcem/pull/1/checks

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant