Intel® oneAPI Math Kernel Library
Ask questions and share information with other developers who use Intel® Math Kernel Library.

VML Rounding Functions v?Modf v?Round questions

Shigeo_Kobayashi
Beginner
443 Views

MKL reference Manual says
   'Halfway values, such as 0.5, -1.5, are rounded off towards even values. An inexact result exception is raised for each changed value.' for v?Modf (VML) function.

I tried it (input=x) and get results(y and z) as follows:
  vdModf( 4, x, y, z ): // No vmlSetMode( mode ) is called before.
      x     y     z
   1.5  1.0  0.5
   0.5  0.0  0.5
  -0.5  0.0 -0.5
  -1.5 -1.0 -0.5

Seems 'Halfway values' are rounded off towards zero ?
And what the 'each changed value' mean?

The manual also says  'f(0.5) = 1, for rounding modes set to plus infinity.' etc for vmdRound( n, a, y, mode ).
Which mode value listed in 'Values of the mode Parameter' I can set for the rounding ?

0 Kudos
8 Replies
Hans_P_Intel
Employee
443 Views

I can reproduce, that v?Modf does not calculate the values as documented (round to even).
Thank you very much for reporting this issue!

The mode argument (global setting, or specified locally by vm?Modf) does not specify the rounding mode. Instead, the mode selects the accuracy, the handling of denormalized values, and how errors are handled. Here is an example:

    const float a[] = { 1.5, 0.5, -0.5, -1.5 };
    const int n = sizeof(a) / sizeof(*a);
    float y, z;

    const MKL_INT64 mode = VML_EP | VML_FTZDAZ_OFF | VML_ERRMODE_IGNORE;
    vmsModf(n, a, y, z, mode);

I have escalated the issue. Please note, that this is either a documentation issue mentioning an incorrect rounding mode, or it is an incorrect rounding mode that does not adhere to the documentation.

0 Kudos
Hans_P_Intel
Employee
443 Views

Regarding your note on vmdRound, this is essentially the same issue as with the v?Modf functions. I have escalated the issue, and also requested to improve the documentation because the "mode" does not document how to adjust the rounding behavior. Looking into "mkl_vml_defines.h" shows that the mode argument determines how the rounding mode of the current floating point environment is picked up. However, there seems to be no example code that recommends on how to adjust the floating point environment.

0 Kudos
Shigeo_Kobayashi
Beginner
443 Views

Hi Hans,
Thank you for your prompt reply.
I expected rounding modes somewhat like "VML_ROUND_TOWARD_PLUS_INFINITY VML_ROUND_TOWARD_MINUS_INFINITY VML_ROUND_TOWARD_ZERO ..." in "mkl_vml_defines.h"(V11 update 2),but they are not in there.
I hope this issue is cleared anyway ... thanks.

0 Kudos
Hans_P_Intel
Employee
443 Views

Shigeo,

I've asked our engineering to check whether it can be supported to specify rounding via the mode argument rather modifying the "FP environment" e.g., somewhat like VML_ROUND_TOWARD_PLUS_INFINITY, VML_ROUND_TOWARD_MINUS_INFINITY, or VML_ROUND_TOWARD_ZERO.

Hans

0 Kudos
Nikita_A_Intel
Employee
443 Views

Hi Shigeo,
Unfortunately there are errors in the documentation of the v?Modf function, as well as in v?Round and v?NearbyInt.

For modf:
This is correct: "The function computes a truncated integer value and remaining fraction part for each vector element."
This is obsolete: "Halfway values, that is, 0.5, -1.5, and the like, are rounded off towards even values. For each changed value, inexact result exception is raised."

There is no way you will be able to change the rounding direction for modf function as it is predefined as truncation or "towards zero".
Same holds true for other rounding functions: ceil, floor, trunc - they use pre-defined rounding direction as it is implied by their names.
round - is also not affected by rounding mode, it always rounds to nearest integer and half-way numbers are always rounded "away from zero".
The only 2 rounding functions that are affected by FP environment are rint and nearbyint - that is you can change the rounding direction e.g. by standard C function fesetround() from <fenv.h> and it will affect the rounding direction inside MKL VML rint and nearbyint.

VML rounding functions behavior is in line with e.g. C99 definitions. And we will fix the typos in our documentation.

Thanks for your post.
Nikita

0 Kudos
Shigeo_Kobayashi
Beginner
443 Views

Hi Nikita,
I understand about the documentation errors. Thank you for your comments !
But I am still confusing ... for programming.
> The only 2 rounding functions that are affected by FP environment are rint and nearbyint - that is you can change the rounding direction ...
If we can change the direction then why we need two?  what the difference between rint  and nearbyint ?
For NearbyInt, document says 'Halfway values, that is, 0.5, -1.5, and the like, are rounded off towards even values.' which (actually do so) means we cannnot change the direction ? 
Could you give me some code examples which change the direction?  
I could not find any description about changing the direction in the document about 'vmlSetMode'.  
I also looked for MKL *.h files, and could not find any MACROs (or something) seeem to control the direction.

> e.g. by standard C function fesetround() from <fenv.h> and it will affect the rounding direction inside MKL VML rint and nearbyint.
Unfortunately, Microsoft C(MSVC) does not support  fesetround() ( <fenv.h> ) ...

0 Kudos
Nikita_A_Intel
Employee
443 Views

Hi Shigeo,
>>If we can change the direction then why we need two?  what the difference between rint  and nearbyint ?
Original specification e.g. C99 standard says that the only difference is that rint "may" be raising Inexact flag if rounding occurred and nearbyint may not. I think we do not care about Inexact flag that much in VML, so the two functions are identical and names are here just for completeness.

>>For NearbyInt, document says 'Halfway values, that ...
As I said, nearbyint documentation is also wrong, so please refer to rint, I found it reasonable.

>>Could you give me some code examples which change the direction?
Well, if you use MSVC, you may look at __control87_2() function, but it is said to be deprecated in case of x64.
Intel C compiler and GCC will give you a fesetround().
You may look up some other examples on the web, but I cannot give you something portable.

I wonder why would you need to change the rounding direction? You may use the dedicated ceil/floor/trunc functions to get directed rounding. You may use rint to get round-to-nearest-even by default (without changing the environment). You may use round to get mathematical rounding.

Thanks,
Nikita

 

0 Kudos
Shigeo_Kobayashi
Beginner
443 Views

Nikita,
I understand now!
> I wonder why would you need to change the rounding direction?
Because it is written in the document...
Thanks again !!

0 Kudos
Reply