Closed sunsided closed 3 months ago
I hate to invoke a fallacy, but this really does seem like a slippery slope. We're simply not going to add traits for every possibly-interesting numeric value, but at least 0 and 1 have status as additive and multiplicative identities. You can also consider From
for more complex constants.
While a square can be implemented trivially (
a * a
), the differentiation of it (2 * a
) causes the issue.
If you accept a * a
, why not use a + a
for the latter? Are you really operating with generic Mul
and not Add
?
Yeah, precisely why I said overkill. :) It's the same discussion in rust-lang about FRAC_
constants.
In my case, it looks like
let one = T::one();
let two = one + one;
let x = vec.x * (one - two * (q2 * q2 + q3 * q3))
+ vec.y * two * (q1 * q2 - q0 * q3)
+ vec.z * two * (q1 * q3 + q0 * q2);
// and
let y = vec.x * (q1 * q2 + q0 * q3)
+ vec.y * (one - two * (q1 * q1 + q3 * q3))
+ vec.z * two * (q2 * q3 - q0 * q1);
// and
let z = vec.x * (q1 * q3 - q0 * q2)
+ vec.y * two * (q2 * q3 + q0 * q1)
+ vec.z * (one - two * (q1 * q1 + q2 * q2));
then in the next it's
let one = T::one();
let two = one + one;
let sinp = two * (w * y - z * x);
// TODO: If sin >= 1.0 || sin <= -1.0, clamp to +/- pi/2 instead
sinp.arcsin()
and then rinse and repeat. PI
is a common factor, and you see the division by two in the note as well.
It's not like there is no solution, it's just getting repetitive and I figured others may have encountered similar situations.
Personally I don't mind having these constants as much, but - as I said - I completely understand it's not exactly a popular standpoint. :)
If you accept a * a, why not use a + a for the latter?
As for that, I totally do accept it. That said, depending on the actual number type the two
will potentially invoke a computation that always can be avoided, whereas the square cannot be constant in general. I'm not talking impl Two for f32
where the compiler easily figures it out, it's more along the lines of FixedPointQ8_24
where we're now shuffling bytes around with every operation. Contrived example, simply to show the point.
Ok, I'm going to take the stance that this isn't really needed. Thanks anyway!
This adds the traits
Two
,ConstTwo
, as well asOneHalf
andConstOneHalf
respectively. It's likeOne
, just twice as good ... or half.This may seem overkill at first glance, but I have found myself re-implementing
repeatedly when implementing digital filters that are either floating- or fixed-point. The need arises for example when differentiating nonlinear equations in order to provide their Laplacians for linear approximation. While a square can be implemented trivially (
a * a
), the differentiation of it (2 * a
) causes the issue.I provided
OneHalf
/ConstOneHalf
since they are dual toTwo
/ConstTwo
. They could be derived, but that would require an additionalDiv<T>
trait bound (whereasMul<T>
is already required byOne
). Given that multiplication is generally faster than division, having it at hand is useful.