- Notifications
You must be signed in to change notification settings - Fork5.1k
Vectorize TensorPrimitives.Cosh/Sinh/Tanh for double#97874
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
This just replicates the float path to be used for double as well, expanding out the constants used to be more precise.
ghost commentedFeb 2, 2024
Tagging subscribers to this area: @dotnet/area-system-numerics |
private constdouble LOGV = 0.6931610107421875; | ||
private constdouble HALFV = 1.000013828277588; | ||
private constdouble INVV2 = 0.24999308586120605; |
tannergoodingFeb 2, 2024 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
These are likely going to introduce more imprecision than necessary.
LOGV
is0.693161
which is meant to be the nearest to the infinitely preciseabs(log(0.5))
, but with a touch of imprecision that accounts for the rounding error over the entire set of logic.HALFV
is likewise1
andINVV2
is likewise0.25
, both with a touch of explicit imprecision.
This comes from the actual algorithm wherecosh(x)
is(e^x + e^-x) / 2
or((e^(2 * x)) + 1) / (2 * e^x)
or(1 + e^(-2 * x)) / (2 * e^-x)
. All of this can simplify down toe^(|x| + log(0.5)) + 0.25 / e^(|x| + log(0.5))
, i.e. the algorithm used here.
AOCL LIBM doesn't provide an official vectorized implementation for double, unfortunately, so we'd have to compute the correct adjustments ourselves. Short of that, simply using0.6931471805599453
,1.0
, and0.25
, is the next best thing and will be the closest to correct for us.
The actual logic used to pick these constants requires us to consider that for the infinitely preciselogv
, the nearest representable float (0.693147182464599609375
) is off by approx0.000000001904654299958
.
The usedLOGV
value used forfloat
ends up picking0.63161f
which is off by0.0000138301822422
instead (note that this is part of the imprecision we then see inHALFV
).
The used value forHALFV
is then off by0.000000001904654309375
from the infinitely precise1.0000138301822422
(note that this is roughly the value that the definedLOGV
is off by).
ForINVV2
it picks0.24999309
which is off from0.25
by0.0000069141387939453125
, I've not done the work to figure out this where this adjustment factors in yet as I've been helping on a few other issues.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Thanks. Meaning I should just update them to 0.6931471805599453, 1.0, and 0.25, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Yeah, for now. I'll work on finishing figuring out the adjustment factor for 0.25 and then get then adjust to the "proper" values for double later.
...ries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorPrimitives.netcore.cs OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
This just replicates the float path to be used for double as well, expanding out the constants used to be more precise.
With#97846,closes#96452.