- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
[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.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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 ?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
[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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
[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]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
[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.
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page