Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // floor(x)
- // Return x rounded toward -inf to integral value
- // Method: Bit twiddling.
- // Exception: Inexact flag raised if x not equal to floor(x)
- #include <iostream>
- #include <bitset>
- using namespace std;
- static const double huge = 1.0e300;
- double floor(double x)
- {
- int i0,i1,j0;
- unsigned int i,j;
- i0 = *(1 + (int*)&x); // __HI(x), the first 32 bits of x
- i1 = *(int*)&x; // __LO(x), the remaining 32 bits of x
- cout << "The binary value of i0 is: " << bitset<32>(i0) << endl;
- cout << "The binary value of i1 is: " << bitset<32>(i1) << endl;
- j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; // 0x7ff is 00000000 00000000 00000111 11111111 (integer 2047)
- // 0x3ff is 00000000 00000000 00000011 11111111 (integer 1023)
- // In the example of -4.5, or 11000000 00010010 00000000 00000000 00000000 00000000 00000000 00000000
- // i0 becomes 11000000 00010010 00000000 00000000 (integer -1072562176)
- // i1 becomes 00000000 00000000 00000000 00000000 (integer 0)
- // j0 first shifts i0 to the right by 20 bits:
- // 00000000 00000000 00001100 00000001 which places the 11-bit exponent portion against the 'right' side.
- // Then we & it with 0x7ff:
- // 00000000 00000000 00001100 00000001 i0 >> 20
- // 00000000 00000000 00000111 11111111 0x7ff
- // 00000000 00000000 00000100 00000001 is the result (integer 1025)
- // Now we subtract 0x3ff, that's 1025 - 1023 = 2.
- // So j0 is 00000000 00000000 00000000 00000010
- cout << "The binary value of j0 is: " << bitset<32>(j0) << endl;
- if (j0 < 20) { // j0 is 2 in this example, so applies.
- if (j0 < 0) { // raise inexact if x != 0; Does not apply to example.
- if (huge + x > 0.0) { // return 0 * sign(x) if |x| < 1
- if (i0 >= 0) {i0 = i1 = 0;}
- else if (((i0 & 0x7fffffff) | i1) != 0)
- {i0 = 0xbff00000; i1=0;}
- }
- }
- else { // j0 was not < 0 so applies.
- i = (0x000fffff) >> j0; // 0x000fffff is 00000000 00001111 11111111 11111111 (integer 1048575)
- // Shifting right by j0, or 2 in the example case is:
- // 00000000 00000011 11111111 11111111 (integer 262143), i is now assigned this value.
- cout << "The binary value of i is: " << bitset<32>(i) << endl;
- if (((i0 & i) | i1) == 0) {
- return x; // x is integral
- }
- // Let's check. First of all, i0 & i:
- // 11000000 00010010 00000000 00000000 i0
- // 00000000 00000011 11111111 11111111 i
- // 00000000 00000010 00000000 00000000 i0 & i
- // Now we need to | it with i1, | is the 'or' operator:
- // 00000000 00000010 00000000 00000000 i0 & i
- // 00000000 00000000 00000000 00000000 i1
- // 00000000 00000010 00000000 00000000 (i0 & i) | i1 (integer 131072)
- // So example does not pass this conditional.
- if (huge + x > 0.0) { // raise inexact flag; True for this example, (10^300 + -4.5) > 0.0
- if (i0 < 0) { // less than 0, as we can see the sign bit is 1, and is therefore negative.
- i0 += (0x00100000) >> j0; // 0x00100000 is integer 1048576, written ambiguously.
- // Let's check. i0 + 1048576 >> j0
- // 00000000 00010000 00000000 00000000 (integer 1048576)
- // 00000000 00000100 00000000 00000000 shifted by j0 (2) is (integer 262144)
- // -1072562176 + 262144 = -1072300032 = i0
- i0 &= (~i);
- // i0 = i0 & (~i);
- // 11000000 00010110 00000000 00000000 i0 (integer -1072300032)
- // 00000000 00000011 11111111 11111111 i
- // 11111111 11111100 00000000 00000000 (~i)
- // 11000000 00010110 00000000 00000000 i0
- // 11000000 00010100 00000000 00000000 i0 & (~i)
- i1=0; // This was already 0 in the example.
- //cout << "I think I might apply" << endl;
- //cout << "The value of x is: " << x << endl;
- }
- }
- }
- }
- else if (j0 > 51) { // j0 is 2 so not in this example. Not running.
- if (j0 == 0x400) { // This loop is not running.
- return x + x; // inf or NaN
- }
- else { // This loop is not running.
- return x; // x is integral
- }
- }
- else { // Not sure if this conditional applies to example, but I haven't reached a return yet.
- // apparently not running.
- i = ((unsigned)(0xffffffff)) >> (j0 - 20);
- //cout << "The binary value of i1 & i is: " << bitset<32>(i1 & i) << endl;
- // unsigned 0xffffffff is 11111111 11111111 11111111 11111111
- // Shifted right by 2 - 20, or -18?
- // apparently this results in 00000000 00000011 11111111 11111111
- // although I get a warning for shifting by a negative, unless j0 - 20 isn't negative?
- if ((i1 & i) == 0) { // Doesn't run either as it belongs to else.
- //cout << "I think I might apply" << endl;
- return x; // x is integral;
- }
- // Let's check.
- // 00000000 00000000 00000000 00000000
- // 00000000 00000011 11111111 11111111
- if (huge + x > 0.0) { // raise inexact flag; Not running.
- //cout << "I think I might apply" << endl;
- if (i0 < 0) {
- //cout << "I think I might apply" << endl;
- if (j0 == 20) {
- i0 += 1;
- }
- else {
- //cout << "I think I might apply" << endl;
- if (j < i1) {
- //cout << "I think I might apply" << endl;
- i0 += 1; // got a carry
- i1 = j;
- }
- }
- }
- cout << "I think I might apply" << endl;
- i1 &= (~i);
- }
- cout << "I think I might apply" << endl;
- }
- cout << "The binary value of i0 (second to last) is: " << bitset<32>(i0) << endl;
- cout << "The value of x is (second to last) is: " << x << endl;
- *(1 + (int*)&x) = i0;
- *(int*)&x = i1;
- //i0 = *(1 + (int*)&x);
- //i1 = *(int*)&x;
- cout << "I apply." << endl;
- cout << "The value of x is: " << x << endl;
- cout << "The binary value of i0 is: " << bitset<32>(i0) << endl;
- cout << "The binary value of i1 is: " << bitset<32>(i1) << endl;
- return x;
- }
- int main() {
- double x = -4.5; // 11000000 00010010 00000000 00000000 00000000 00000000 00000000 00000000
- double y = floor(x);
- cout << "the floor of " << x << " is " << y << endl; // Prints -5
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement