1 #include "CLHEP/Random/DoubConv.hh"
2 
3 #include <sstream>
4 #include <iomanip>
5 
6 namespace CLHEP {
7 
8 CLHEP_THREAD_LOCAL bool DoubConv::byte_order_known = false;
9 CLHEP_THREAD_LOCAL int  DoubConv::byte_order[8];
10 
fill_byte_order()11 void DoubConv::fill_byte_order () {
12   double x = 1.0;
13   int t30 = 1 << 30;
14   int t22 = 1 << 22;
15   x *= t30;
16   x *= t22;
17   double y = 1;
18   double z = 1;
19   x *= z;
20   for (int k=0; k<6; k++) {
21     x += y*z;
22     y += 1;
23     z *= 256;
24   }
25   // x, in IEEE format, would now be 0x4330060504030201
26   DB8 xb;
27   xb.d = x;
28   int n;
29   static const int UNSET = -1;
30   for (n=0; n<8; n++) {
31     byte_order[n] = UNSET;
32   }
33   int order;
34   for (n=0; n<8; n++) {
35     switch ( xb.b[n] ) {
36       case 0x43:
37         order = 0;
38         break;
39       case 0x30:
40         order = 1;
41         break;
42       case 0x06:
43         order = 2;
44         break;
45       case 0x05:
46         order = 3;
47         break;
48       case 0x04:
49         order = 4;
50         break;
51       case 0x03:
52         order = 5;
53         break;
54       case 0x02:
55         order = 6;
56         break;
57       case 0x01:
58         order = 7;
59         break;
60       default:
61         throw DoubConvException(
62 		"Cannot determine byte-ordering of doubles on this system");
63     }
64     if (byte_order[n] != UNSET) {
65         throw DoubConvException(
66 		"Confusion in byte-ordering of doubles on this system");
67     }
68     byte_order[n] = order;
69     byte_order_known = true;
70   }
71   return;
72 }
73 
d2x(double d)74 std::string DoubConv::d2x(double d) {
75   if ( !byte_order_known ) fill_byte_order ();
76   DB8 db;
77   db.d = d;
78   std::ostringstream ss;
79   for (int i=0; i<8; ++i) {
80     int k = byte_order[i];
81     ss << std::hex << std::setw(2) << std::setfill('0') << (int)db.b[k];
82   }
83   return ss.str();
84 }
85 
dto2longs(double d)86 std::vector<unsigned long> DoubConv::dto2longs(double d) {
87   std::vector<unsigned long> v(2);
88   if ( !byte_order_known ) fill_byte_order ();
89   DB8 db;
90   db.d = d;
91   v[0] =   ((static_cast<unsigned long>(db.b[byte_order[0]])) << 24)
92          | ((static_cast<unsigned long>(db.b[byte_order[1]])) << 16)
93          | ((static_cast<unsigned long>(db.b[byte_order[2]])) <<  8)
94          | ((static_cast<unsigned long>(db.b[byte_order[3]]))      );
95   v[1] =   ((static_cast<unsigned long>(db.b[byte_order[4]])) << 24)
96          | ((static_cast<unsigned long>(db.b[byte_order[5]])) << 16)
97          | ((static_cast<unsigned long>(db.b[byte_order[6]])) <<  8)
98          | ((static_cast<unsigned long>(db.b[byte_order[7]]))      );
99   return v;
100 }
101 
longs2double(const std::vector<unsigned long> & v)102 double DoubConv::longs2double (const std::vector<unsigned long> & v) {
103   DB8 db;
104   unsigned char bytes[8];
105   if ( !byte_order_known ) fill_byte_order ();
106   bytes[0] = static_cast<unsigned char>((v[0] >> 24) & 0xFF);
107   bytes[1] = static_cast<unsigned char>((v[0] >> 16) & 0xFF);
108   bytes[2] = static_cast<unsigned char>((v[0] >>  8) & 0xFF);
109   bytes[3] = static_cast<unsigned char>((v[0]      ) & 0xFF);
110   bytes[4] = static_cast<unsigned char>((v[1] >> 24) & 0xFF);
111   bytes[5] = static_cast<unsigned char>((v[1] >> 16) & 0xFF);
112   bytes[6] = static_cast<unsigned char>((v[1] >>  8) & 0xFF);
113   bytes[7] = static_cast<unsigned char>((v[1]      ) & 0xFF);
114   for (int i=0; i<8; ++i) {
115     db.b[byte_order[i]] =  bytes[i];
116   }
117   return db.d;
118 }
119 
120 } // end namespace CLHEP
121