Advertisement
Lorfa

Floor_from_Sun

May 25th, 2023 (edited)
591
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.54 KB | None | 0 0
  1. // floor(x)
  2. // Return x rounded toward -inf to integral value
  3. // Method: Bit twiddling.
  4. // Exception: Inexact flag raised if x not equal to floor(x)
  5.  
  6. #include <iostream>
  7. #include <bitset>
  8. using namespace std;
  9.  
  10. static const double huge = 1.0e300;
  11.  
  12. double floor(double x)
  13.  
  14. {
  15.     int i0,i1,j0;
  16.    
  17.     unsigned int i,j;
  18.    
  19.     i0 =  *(1 + (int*)&x);              // __HI(x), the first 32 bits of x
  20.    
  21.     i1 =  *(int*)&x;                    // __LO(x), the remaining 32 bits of x
  22.    
  23.     cout << "The binary value of i0 is: " << bitset<32>(i0) << endl;
  24.     cout << "The binary value of i1 is: " << bitset<32>(i1) << endl;
  25.    
  26.     j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;  // 0x7ff is 00000000 00000000 00000111 11111111 (integer 2047)
  27.                                         // 0x3ff is 00000000 00000000 00000011 11111111 (integer 1023)
  28.                                        
  29.     // In the example of -4.5, or 11000000 00010010 00000000 00000000 00000000 00000000 00000000 00000000
  30.     // i0 becomes 11000000 00010010 00000000 00000000 (integer -1072562176)
  31.     // i1 becomes 00000000 00000000 00000000 00000000 (integer 0)
  32.     // j0 first shifts i0 to the right by 20 bits:
  33.     // 00000000 00000000 00001100 00000001 which places the 11-bit exponent portion against the 'right' side.
  34.     // Then we & it with 0x7ff:
  35.     // 00000000 00000000 00001100 00000001 i0 >> 20
  36.     // 00000000 00000000 00000111 11111111 0x7ff
  37.     // 00000000 00000000 00000100 00000001 is the result (integer 1025)
  38.     // Now we subtract 0x3ff, that's 1025 - 1023 = 2.
  39.     // So j0 is 00000000 00000000 00000000 00000010
  40.    
  41.     cout << "The binary value of j0 is: " << bitset<32>(j0) << endl;
  42.        
  43.     if (j0 < 20) {                      // j0 is 2 in this example, so applies.
  44.        
  45.         if (j0 < 0) {                   // raise inexact if x != 0; Does not apply to example.
  46.        
  47.             if (huge + x > 0.0) {       // return 0 * sign(x) if |x| < 1
  48.            
  49.                 if (i0 >= 0) {i0 = i1 = 0;}
  50.                
  51.                     else if (((i0 & 0x7fffffff) | i1) != 0)
  52.                
  53.                     {i0 = 0xbff00000; i1=0;}
  54.                                 }
  55.        
  56.                     }  
  57.        
  58.             else {                      // j0 was not < 0 so applies.
  59.            
  60.                 i = (0x000fffff) >> j0; // 0x000fffff is 00000000 00001111 11111111 11111111 (integer 1048575)
  61.                
  62.                 // Shifting right by j0, or 2 in the example case is:
  63.                 // 00000000 00000011 11111111 11111111 (integer 262143), i is now assigned this value.
  64.                
  65.                 cout << "The binary value of  i is: " << bitset<32>(i) << endl;
  66.                        
  67.                 if (((i0 & i) | i1) == 0)   {
  68.                                
  69.                 return x; // x is integral
  70.                
  71.                                             }
  72.                
  73.                 // Let's check. First of all, i0 & i:
  74.                 // 11000000 00010010 00000000 00000000 i0
  75.                 // 00000000 00000011 11111111 11111111 i
  76.                 // 00000000 00000010 00000000 00000000 i0 & i
  77.                 // Now we need to | it with i1, | is the 'or' operator:
  78.                 // 00000000 00000010 00000000 00000000 i0 & i
  79.                 // 00000000 00000000 00000000 00000000 i1
  80.                 // 00000000 00000010 00000000 00000000 (i0 & i) | i1 (integer 131072)
  81.                 // So example does not pass this conditional.              
  82.        
  83.                     if (huge + x > 0.0) {   // raise inexact flag; True for this example, (10^300 + -4.5) > 0.0
  84.                
  85.                         if (i0 < 0) {       // less than 0, as we can see the sign bit is 1, and is therefore negative.
  86.                                        
  87.                             i0 += (0x00100000) >> j0; // 0x00100000 is integer 1048576, written ambiguously.
  88.                            
  89.                             // Let's check. i0 + 1048576 >> j0
  90.                             // 00000000 00010000 00000000 00000000 (integer 1048576)
  91.                             // 00000000 00000100 00000000 00000000 shifted by j0 (2) is (integer 262144)
  92.                             // -1072562176 + 262144 = -1072300032 = i0
  93.                    
  94.                             i0 &= (~i);
  95.                            
  96.                             // i0 = i0 & (~i);
  97.                             // 11000000 00010110 00000000 00000000 i0 (integer -1072300032)
  98.                             // 00000000 00000011 11111111 11111111 i
  99.                             // 11111111 11111100 00000000 00000000 (~i)
  100.                             // 11000000 00010110 00000000 00000000 i0
  101.                             // 11000000 00010100 00000000 00000000 i0 & (~i)
  102.                    
  103.                             i1=0; // This was already 0 in the example.
  104.                            
  105.                             //cout << "I think I might apply" << endl;
  106.                             //cout << "The value of x is: " << x << endl;
  107.                        
  108.                             }
  109.                         }
  110.                 }
  111.        
  112.     }
  113.    
  114.          else if (j0 > 51) {                // j0 is 2 so not in this example. Not running.
  115.                
  116.             if (j0 == 0x400) {              // This loop is not running.
  117.                
  118.                 return x + x;   // inf or NaN
  119.        
  120.                         }
  121.            
  122.                 else {                  // This loop is not running.
  123.            
  124.                     return x;               // x is integral
  125.                 }
  126.        
  127.             }
  128.    
  129.         else {                              // Not sure if this conditional applies to example, but I haven't reached a return yet.
  130.                                             // apparently not running.
  131.                
  132.         i = ((unsigned)(0xffffffff)) >> (j0 - 20);
  133.        
  134.         //cout << "The binary value of i1 & i is: " << bitset<32>(i1 & i) << endl;
  135.         // unsigned 0xffffffff is 11111111 11111111 11111111 11111111
  136.         // Shifted right by 2 - 20, or -18?
  137.         // apparently this results in 00000000 00000011 11111111 11111111
  138.         // although I get a warning for shifting by a negative, unless j0 - 20 isn't negative?
  139.        
  140.                 if ((i1 & i) == 0) {            // Doesn't run either as it belongs to else.
  141.        
  142.                 //cout << "I think I might apply" << endl;
  143.                 return x;   // x is integral;
  144.                             }
  145.        
  146.         // Let's check.
  147.         // 00000000 00000000 00000000 00000000
  148.         // 00000000 00000011 11111111 11111111
  149.        
  150.         if (huge + x > 0.0) {           // raise inexact flag; Not running.
  151.        
  152.             //cout << "I think I might apply" << endl;
  153.        
  154.             if (i0 < 0) {
  155.                
  156.                 //cout << "I think I might apply" << endl;
  157.            
  158.                 if (j0 == 20) {
  159.                
  160.                         i0 += 1;
  161.                
  162.                             }
  163.                
  164.                 else {
  165.            
  166.                     //cout << "I think I might apply" << endl;
  167.                
  168.                     if (j < i1) {
  169.            
  170.                         //cout << "I think I might apply" << endl;
  171.            
  172.                         i0 += 1;        // got a carry
  173.            
  174.                         i1 = j;
  175.                        
  176.                         }
  177.            
  178.                     }
  179.                 }
  180.            
  181.             cout << "I think I might apply" << endl;
  182.         i1 &= (~i);
  183.        
  184.         }
  185.        
  186.         cout << "I think I might apply" << endl;
  187.     }
  188.        
  189.     cout << "The binary value of i0 (second to last) is: " << bitset<32>(i0) << endl;
  190.     cout << "The value of x is (second to last) is: " << x << endl;
  191.        
  192.     *(1 + (int*)&x) = i0;
  193.    
  194.     *(int*)&x = i1;
  195.    
  196.     //i0 = *(1 + (int*)&x);
  197.    
  198.     //i1 = *(int*)&x;
  199.        
  200.     cout << "I apply." << endl;
  201.     cout << "The value of x is: " << x << endl;
  202.     cout << "The binary value of i0 is: " << bitset<32>(i0) << endl;
  203.     cout << "The binary value of i1 is: " << bitset<32>(i1) << endl;
  204.    
  205.     return x;
  206.    
  207. }
  208.  
  209. int main() {
  210.        
  211.     double x = -4.5; // 11000000 00010010 00000000 00000000 00000000 00000000 00000000 00000000
  212.    
  213.     double y = floor(x);
  214.    
  215.     cout << "the floor of " << x << " is " << y << endl; // Prints -5
  216.    
  217.     return 0;
  218. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement