Turn on suggestions

Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.

Showing results for

- Intel Community
- Software Development Technologies
- Intel® ISA Extensions
- Check if a floating point is actually an Integer

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Mute
- Printer Friendly Page

Highlighted

anujgarg2004gmail_co

Beginner

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

01-07-2009
09:41 AM

58 Views

i need a method which given a floating point can check whether it is actually an integral value or not. Currently i am using something like this.

bool IsInteger(double dbl)

{

long lwT = (long)dbl;

double dblT = (double)lwT;

return (LowerDWORD(dblT) == LowerDWORD(dbl) && HigherDWORD(dblT) == HigherDWORD(dbl));

}

This method happens to consume 50% of my time blaming _ftol2_sse and floor functions.

Is there any better method to do this? Any assembly instruction possibly?

Accepted Solutions

Highlighted
I presume this is what you want:

ILevi1

Valued Contributor I

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

01-27-2009
07:47 AM

58 Views

[cpp]bool IsInteger(double dVal) { __int64 iVal = (__int64)dVal; double tVal = (double)iVal; return (tVal == dVal) ? true : false; } [/cpp]You can try to use this code as well:

[cpp]bool IsInteger(double dVal) { const double magic = 68719476736.0 * 1.5; double tVal1 = dVal + magic; int iVal = ((int*)&tVal1)[0] >> 16; double tVal2 = iVal; return (tVal2 == dVal) ? true : false; } [/cpp]However, in a quick test I just performed the following code seems to be the fastest:

[cpp]bool IsInteger(double dVal) { int iVal = (int)dVal; double tVal = (double)iVal; return (tVal == dVal) ? true : false; } [/cpp]That is of course assuming that your double will never exceed the range of a 32-bit integer.

9 Replies

Highlighted
*
*

There must be something you haven't told us, to explain why you would do something so convoluted.

dblT == dbl

looks like it makes more sense.

dbl == rint(dbl)

or even (if using SSE2)

dbl == (long int)dbl

(depending on what you mean by integral values)

might be faster, if you don't need to support old compilers, or can use equivalent in-line asm.

TimP

Black Belt

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

01-07-2009
10:03 AM

58 Views

Quoting - anujgarg2004gmail.com

i need a method which given a floating point can check whether it is actually an integral value or not. Currently i am using something like this.

bool IsInteger(double dbl)

{

long lwT = (long)dbl;

double dblT = (double)lwT;

return (LowerDWORD(dblT) == LowerDWORD(dbl) && HigherDWORD(dblT) == HigherDWORD(dbl));

}

This method happens to consume 50% of my time blaming _ftol2_sse and floor functions.

Is there any better method to do this? Any assembly instruction possibly?

There must be something you haven't told us, to explain why you would do something so convoluted.

dblT == dbl

looks like it makes more sense.

dbl == rint(dbl)

or even (if using SSE2)

dbl == (long int)dbl

(depending on what you mean by integral values)

might be faster, if you don't need to support old compilers, or can use equivalent in-line asm.

Highlighted
*
*

There must be something you haven't told us, to explain why you would do something so convoluted.

dblT == dbl

looks like it makes more sense.

dbl == rint(dbl)

or even (if using SSE2)

dbl == (long int)dbl

(depending on what you mean by integral values)

might be faster, if you don't need to support old compilers, or can use equivalent in-line asm.

anujgarg2004gmail_co

Beginner

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

01-07-2009
12:21 PM

58 Views

Quoting - tim18

There must be something you haven't told us, to explain why you would do something so convoluted.

dblT == dbl

looks like it makes more sense.

dbl == rint(dbl)

or even (if using SSE2)

dbl == (long int)dbl

(depending on what you mean by integral values)

might be faster, if you don't need to support old compilers, or can use equivalent in-line asm.

By integral value i mean that if there is something of the sort 23.000000000 then it is integral for me (digits of presion depends maximum size of INT32.

this whole converting to INT/LONG is kinda expensive. i was wondering if there is some assembly instruction similar to that of rint(). Unfortunately there is no rint() on windows. Do you know any workaround?

Isn't rint() same as (mantisa = mantisa & (0xFFFFFFFF << (53 - ( 127 - exp )))

so in that case instead of a typecast i can simple do a couple of Bit operations. Do you think it will be cheaper than typecasting ?

Highlighted

You hinted that you might use /arch:SSE2 (or X64, where that is the default).Changing rounding mode to make an (long int) castwould be quite expensive in original x87 code. So, you really need to decide about such instruction set issues, if you want to optimize performance.

One point about the difference between rint() and (long int) is that the former admits of integral values which exceed LONG_MAX.If you exclude operation on such values, and choose SSE2, you don't really need rint(). Particulary on a forum meant for future instruction sets, it is a bit out of place to insist you won't use a compiler from this century. At least, I have no intention of going there without current compiler support.

If you do want to handle numbers beyond LONG_MAX, and want to write your own replacement for rint(), using SSE2 code generation, for 0 < x < 1/DBL_EPSILON, ((x + 1/DBL_EPSILON) - 1/DBL/EPSILON) will work, if you use a C89 compiler. For negative values, you just change the sign, and for |x| > 1/DBL_EPSILON you know that it is already an integral value.

TimP

Black Belt

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

01-07-2009
01:11 PM

58 Views

You hinted that you might use /arch:SSE2 (or X64, where that is the default).Changing rounding mode to make an (long int) castwould be quite expensive in original x87 code. So, you really need to decide about such instruction set issues, if you want to optimize performance.

One point about the difference between rint() and (long int) is that the former admits of integral values which exceed LONG_MAX.If you exclude operation on such values, and choose SSE2, you don't really need rint(). Particulary on a forum meant for future instruction sets, it is a bit out of place to insist you won't use a compiler from this century. At least, I have no intention of going there without current compiler support.

If you do want to handle numbers beyond LONG_MAX, and want to write your own replacement for rint(), using SSE2 code generation, for 0 < x < 1/DBL_EPSILON, ((x + 1/DBL_EPSILON) - 1/DBL/EPSILON) will work, if you use a C89 compiler. For negative values, you just change the sign, and for |x| > 1/DBL_EPSILON you know that it is already an integral value.

Highlighted
I presume this is what you want:

ILevi1

Valued Contributor I

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

01-27-2009
07:47 AM

59 Views

[cpp]bool IsInteger(double dVal) { __int64 iVal = (__int64)dVal; double tVal = (double)iVal; return (tVal == dVal) ? true : false; } [/cpp]You can try to use this code as well:

[cpp]bool IsInteger(double dVal) { const double magic = 68719476736.0 * 1.5; double tVal1 = dVal + magic; int iVal = ((int*)&tVal1)[0] >> 16; double tVal2 = iVal; return (tVal2 == dVal) ? true : false; } [/cpp]However, in a quick test I just performed the following code seems to be the fastest:

[cpp]bool IsInteger(double dVal) { int iVal = (int)dVal; double tVal = (double)iVal; return (tVal == dVal) ? true : false; } [/cpp]That is of course assuming that your double will never exceed the range of a 32-bit integer.

Highlighted
Here's another approach:

bool __declspec(noinline) isInteger(double x)

{

__int64 binary = (__int64&)x;

int exponent = (int)((binary & 0x7FF0000000000000) >> 52) - 1023;

__int64 mantissa = (binary & 0x000FFFFFFFFFFFFF) | 0x0010000000000000;

__int64 decimals = (exponent >= 0) ? 0x000FFFFFFFFFFFFF >> exponent : 0x001FFFFFFFFFFFFF;

return x == 0.0 || !(mantissa & decimals);

}

It should also work for integers that don't fit in the 64-bit range. I haven't checked the behavior for denormals and NaNs so you might want to test that.

It works by testing whether any of the mantissa bits below the decimal point are set. It should perform quite well, although it won't be as fast as an SSE2 conversion back and forth.

capens__nicolas

New Contributor I

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

01-28-2009
04:18 AM

58 Views

bool __declspec(noinline) isInteger(double x)

{

__int64 binary = (__int64&)x;

int exponent = (int)((binary & 0x7FF0000000000000) >> 52) - 1023;

__int64 mantissa = (binary & 0x000FFFFFFFFFFFFF) | 0x0010000000000000;

__int64 decimals = (exponent >= 0) ? 0x000FFFFFFFFFFFFF >> exponent : 0x001FFFFFFFFFFFFF;

return x == 0.0 || !(mantissa & decimals);

}

It should also work for integers that don't fit in the 64-bit range. I haven't checked the behavior for denormals and NaNs so you might want to test that.

It works by testing whether any of the mantissa bits below the decimal point are set. It should perform quite well, although it won't be as fast as an SSE2 conversion back and forth.

Highlighted
Please ignore the __declspec(noinline) part, I used it to check the generated assembly code. Updated version with syntax highlighting:

capens__nicolas

New Contributor I

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

01-28-2009
04:30 AM

58 Views

[cpp]bool isInteger(double x) { __int64 binary = (__int64&)x; int exponent = (int)((binary & 0x7FF0000000000000) >> 52) - 1023; __int64 mantissa = (binary & 0x000FFFFFFFFFFFFF) | 0x0010000000000000; __int64 decimals = (exponent >= 0) ? 0x000FFFFFFFFFFFFF >> exponent : 0x001FFFFFFFFFFFFF; return x == 0.0 || !(mantissa & decimals); }[/cpp]

Highlighted
*I presume this is what you want:*

the last code is exactly was i was doing. it seemed to be a bit to expensive in the begining but after some experimentations with all of these mentioned stratergies, i realized this one is indeed the best. Thanx for all your replies.

anujgarg2004gmail_co

Beginner

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

02-05-2009
01:23 AM

58 Views

Quoting - Igor Levicki

You can try to use this code as well:[cpp]bool IsInteger(double dVal) { __int64 iVal = (__int64)dVal; double tVal = (double)iVal; return (tVal == dVal) ? true : false; } [/cpp]

[cpp]bool IsInteger(double dVal) { const double magic = 68719476736.0 * 1.5; double tVal1 = dVal + magic; int iVal = ((int*)&tVal1)[0] >> 16; double tVal2 = iVal; return (tVal2 == dVal) ? true : false; } [/cpp]However, in a quick test I just performed the following code seems to be the fastest:

[cpp]bool IsInteger(double dVal) { int iVal = (int)dVal; double tVal = (double)iVal; return (tVal == dVal) ? true : false; } [/cpp]That is of course assuming that your double will never exceed the range of a 32-bit integer.

the last code is exactly was i was doing. it seemed to be a bit to expensive in the begining but after some experimentations with all of these mentioned stratergies, i realized this one is indeed the best. Thanx for all your replies.

Highlighted
*
*

the last code is exactly was i was doing. it seemed to be a bit to expensive in the begining but after some experimentations with all of these mentioned stratergies, i realized this one is indeed the best. Thanx for all your replies.
Casting double to int and back to double would be quite slow in x87 code, but no problem in other common instruction sets, within the range limitations.

TimP

Black Belt

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

02-05-2009
05:28 AM

58 Views

Quoting - anujgarg2004gmail.com

the last code is exactly was i was doing. it seemed to be a bit to expensive in the begining but after some experimentations with all of these mentioned stratergies, i realized this one is indeed the best. Thanx for all your replies.

Highlighted
*
*

the last code is exactly was i was doing. it seemed to be a bit to expensive in the begining but after some experimentations with all of these mentioned stratergies, i realized this one is indeed the best. Thanx for all your replies.

You are welcome. If you find my reply helpfull please don't forget to rate my post and/or select it as a best answer. Thank you.

ILevi1

Valued Contributor I

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

02-13-2009
11:27 AM

58 Views

Quoting - anujgarg2004gmail.com

the last code is exactly was i was doing. it seemed to be a bit to expensive in the begining but after some experimentations with all of these mentioned stratergies, i realized this one is indeed the best. Thanx for all your replies.

You are welcome. If you find my reply helpfull please don't forget to rate my post and/or select it as a best answer. Thank you.

For more complete information about compiler optimizations, see our Optimization Notice.