[libc-commits] [PATCH] D127046: [libc][math] fmod/fmodf implementation.
Kirill Okhotnikov via Phabricator via libc-commits
libc-commits at lists.llvm.org
Tue Jun 21 05:30:48 PDT 2022
orex added inline comments.
================
Comment at: libc/src/__support/FPUtil/FPBits.h:173
+ // offset: +1 for sign, but -1 for implicit first bit
+ int lz = fputil::clz(number) - FloatProp::EXPONENT_WIDTH;
+ number <<= lz;
----------------
lntue wrote:
> For safety, you might need to add a quick return for when `number == 0`:
> ```
> if (unlikely(number == 0)) return zero ...
> ```
It was Siva suggestion to move the function here. There is another class called `NormalFloat` which can handle such things. I propose to move the function back to FMod and implement "full" functionality in that class. What do you think? `if number == 0` is not only one case which we need to check. `ep` value after processing below should also be checked for overflow.
================
Comment at: libc/src/__support/FPUtil/generic/FMod.h:70
+// https://en.cppreference.com/w/cpp/numeric/math/fmod
+template <typename T> class FModCStandardWrapper {
+
----------------
lntue wrote:
> lntue wrote:
> > There is only one public method for this class, you can replace `class` with `struct` and remove `public:`.
> Maybe rename the class to `FModErrorHandler` and add to the comment: following C99 standard with a link to `https://en.cppreference.com/w/c/numeric/math/fmod`
Sure.
================
Comment at: libc/src/__support/FPUtil/generic/FMod.h:70
+// https://en.cppreference.com/w/cpp/numeric/math/fmod
+template <typename T> class FModCStandardWrapper {
+
----------------
orex wrote:
> lntue wrote:
> > lntue wrote:
> > > There is only one public method for this class, you can replace `class` with `struct` and remove `public:`.
> > Maybe rename the class to `FModErrorHandler` and add to the comment: following C99 standard with a link to `https://en.cppreference.com/w/c/numeric/math/fmod`
> Sure.
It is not an error handler, but special numbers `cases` processor. Do you have another name in mind? If no, let's go for Error.
================
Comment at: libc/src/__support/FPUtil/generic/FMod.h:81
+
+ if (unlikely(fputil::isnan(x) || fputil::isnan(y))) {
+ out = fputil::quiet_NaN(T(0));
----------------
lntue wrote:
> From the C standard, `fmod(0, NaN)` and `fmod(0, inf)` should be `0`
> ```
> If x is ±0 and y is not zero, ±0 is returned
> ```
Thank you. This is a very good comment. Obviously C standard "F.10.7.1" is not full. It do not describe at all, for example, NaN NaN case. I also do not think, that fmod(0, NaN) should return zero. I prefer to go for better consistent standard which are described here
https://pubs.opengroup.org/onlinepubs/9699919799/functions/fmod.html
https://en.cppreference.com/w/c/numeric/math/fmod
What do you think about this?
================
Comment at: libc/src/__support/FPUtil/generic/FMod.h:87
+ if (unlikely(fputil::isinf(x) || y == 0)) {
+ force_eval<T>((x * y) / (y * x));
+ out = with_errno(fputil::quiet_NaN(T(0)), EDOM);
----------------
lntue wrote:
> What's the main purpose of this evaluation?
Thank you for the comment. I don't know any other approach to raise floating-point exception. Please suggest me something better.
================
Comment at: libc/src/__support/FPUtil/generic/FMod.h:95
+ }
+ if (unlikely(x == 0)) {
+ out = x;
----------------
lntue wrote:
> This should be moved to above `isnan(x) || isnan(y)`, I don't think it is hit here.
A question about standard. See above.
================
Comment at: libc/src/__support/FPUtil/generic/FMod.h:99
+ }
+ return false;
+ }
----------------
lntue wrote:
> I don't think this line is hit, and all of the `unlikely`'s above are not needed.
`return false`. Yes you are right, but I can't return nothing from the function. It will be a warning `warning: non-void function does not return a value in all control paths` I don't want my code to produce such things.
`unlikely` I would like to explicitly say compiler to make just one conditional jump in the function. It is not so big problem, of course, I can remove this.
================
Comment at: libc/src/__support/FPUtil/generic/FMod.h:103
+
+template <typename T> class FModGCCInspiredWrapper {
+
----------------
lntue wrote:
> We don't need this anymore, just use C standard.
See above.
================
Comment at: libc/src/__support/FPUtil/generic/FMod.h:144
+ template <bool B = InverseMultiplication>
+ typename std::enable_if<
+ !B, intU_t>::type inline constexpr static division_loop(int n,
----------------
lntue wrote:
> Instead of using `enable_if`with the boolean `InverseMultiplication`, it might be better to separate these 2 versions of `division_loop` into 2 separate structs and then pass them to the second template argument, similar to the way you do exceptional handling. Something like:
> ```
> // Comments explains what these functions do and what the input parameters are.
> template<typename T>
> struct FModDivisionLoop {
> static T execute(int n, int hyltzeros, T hx, T hy) { ... }
> };
> template<typename T>
> struct FModInverseMultiplicationLoop {
> static T execute( ... )
> };
> ```
> Then the main class will be something like:
> ```
> template<typename T, class ErrorHandler = FModErrorHandler<T>, class MainLoop = InverseMultiplicationLoop<T>>
> class FMod { ... };
> ```
Thank you. Sounds reasonable. I will do this.
================
Comment at: libc/src/__support/FPUtil/generic/FMod.h:265
+public:
+ static inline T make(T x, T y) {
+ if (T out; Wrapper::PreCheck(x, y, out))
----------------
lntue wrote:
> `FMod<T>::eval()` or `execute` instead of `make`?
Yes. Sounds better. Thank you.
================
Comment at: libc/src/__support/FPUtil/generic/FMod.h:25
+// Some common cases, like abs(x) < abs(y) or abs(x) < 1000 * abs(y) are
+// treated specially to increase performance. The part of checking special
+// cases, numbers NaN, INF etc. is inspired by GCC libm implementation.
----------------
lntue wrote:
> nit: treated *separately*
Sure.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D127046/new/
https://reviews.llvm.org/D127046
More information about the libc-commits
mailing list