Skip to content

Add float16 exp/log math functions via promotion to float32 - #3228

Open
dcsid wants to merge 3 commits into
google:masterfrom
dcsid:f16/math-exp-log
Open

Add float16 exp/log math functions via promotion to float32#3228
dcsid wants to merge 3 commits into
google:masterfrom
dcsid:f16/math-exp-log

Conversation

@dcsid

@dcsid dcsid commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Towards #2682 — first PR of the series discussed there: adds float16_t overloads of Exp, Exp2, Expm1, Log, Log2, Log10 and Log1p in a new hwy/contrib/math/f16_math-inl.h, which promote to float32, evaluate the existing float32 kernels, and demote the result via DemoteTo + Combine as suggested (no OrderedDemote2To for f32->f16).

Notes:

  • The overloads take Simd<float16_t, N, kPow2> so they are more specialized than the unconstrained templates in math-inl.h; a SFINAE-constrained overload with the same signature would be ambiguous. No changes to math-inl.h are needed.
  • Works on all targets, including when HWY_HAVE_FLOAT16 is 0 — only ops from the always-supported list in quick_reference.md are used. Vectors that fit in half of the widest vector use a single promotion; wider vectors (and RVV tags already at HWY_MAX_POW2, where Rebind to float would be illegal) take a per-half path.
  • The new f16_math_test exhaustively tests all float16 bit patterns in each function's documented range, in vector batches so that lane placement is also verified. Max observed error is 1 ULP against a single-rounded double-precision reference, with infinities required to match exactly.

Follow-up PRs will add the remaining functions in batches, with Hypot and other special cases last.

@jan-wassenberg jan-wassenberg left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work, generally LGTM, just two quick questions.
What's the test runtime like for exhaustive enumeration? Should we also parallelize that?

Comment thread hwy/contrib/math/f16_math-inl.h Outdated
@dcsid

dcsid commented Jul 24, 2026

Copy link
Copy Markdown
Contributor Author

Done in 3b32355. Added HWY_IF_NOT_SPECIAL_FLOAT_D to the seven declarations in math-inl.h and switched the float16 overloads to plain HWY_IF_F16_D, dropping the Simd<float16_t, N, kPow2> specialization.

One wrinkle: the definitions are separated from the declarations, and a default template argument may not be restated, so the definitions repeat the EnableIf without the = nullptr.

@dcsid

dcsid commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

Runtime is negligible: the full 65,536-pattern sweep is ~7 ms per function per target (~96 ms for the whole binary), so parallelizing doesn't seem worth it.

The red jobs look like infra: ppc64le (Power10) failed in gtest_discover_tests with empty output from convert_test under QEMU (a contrib-off job), which fail-fast then cancelled the sibling multiarch jobs; both AArch64 jobs ended with "runner has received a shutdown signal". Happy to have them re-run.

jan-wassenberg
jan-wassenberg previously approved these changes Jul 27, 2026

@jan-wassenberg jan-wassenberg left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for updating! A bit unfortunate about the default arg, ideally we wouldn't declare functions beforehand, but would define CallX after X(). I'll take a TODO to clean that up at some point.

dcsid added 2 commits August 9, 2026 14:13
Towards google#2682. Adds hwy/contrib/math/f16_math-inl.h with float16_t
overloads of Exp, Exp2, Expm1, Log, Log2, Log10 and Log1p that promote
to float32, evaluate the existing float32 kernels, and demote the
result via DemoteTo + Combine (there is no OrderedDemote2To for
f32->f16). Works on all targets, even when HWY_HAVE_FLOAT16 is 0;
vectors already at HWY_MAX_POW2 (possible on RVV) take the per-half
path so the float32 tag never exceeds the maximum kPow2.

The new f16_math_test exhaustively sweeps all float16 bit patterns in
the documented range of each function, in vector batches so that lane
placement is also verified. Results are within 1 ULP of the correctly
rounded float16 result (single-rounding double-precision reference;
infinities must match exactly).
Per review: add HWY_IF_NOT_SPECIAL_FLOAT_D to the Exp/Exp2/Expm1/Log/
Log2/Log10/Log1p declarations (definitions repeat the EnableIf without
the default argument, which may not be restated), so the float16
overloads can use HWY_IF_F16_D instead of relying on partial ordering
of Simd<float16_t, N, kPow2>.
@dcsid
dcsid force-pushed the f16/math-exp-log branch from 3b32355 to 060856f Compare August 9, 2026 18:14
@jan-wassenberg

Copy link
Copy Markdown
Member

Internal CI is failing on Arm:
f16x32: Exp(-13.882812) expected 9.536743E-07 actual 1.072884E-06 ulp 2 max ulp 1

Please update the ulp tolerance to 2 :)

Internal CI reported Exp(-13.882812) off by 2 ULP on Arm. The result
there is 9.3e-07, a float16 subnormal: spacing is a fixed 2^-24, so the
smallest results hold only about four significant bits and a float32
result that differs slightly between targets lands two float16 values
away.

Exp, Exp2, Expm1 and Log1p are the functions whose results reach the
subnormals, so all four now allow 2 ULP; the logarithms never return a
subnormal and stay at 1.

@jan-wassenberg jan-wassenberg left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for updating :)

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants