maintenance release 2.3.1
[libcds.git] / cds / algo / bit_reversal.h
1 /*
2     This file is a part of libcds - Concurrent Data Structures library
3
4     (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
5
6     Source code repo: http://github.com/khizmax/libcds/
7     Download: http://sourceforge.net/projects/libcds/files/
8
9     Redistribution and use in source and binary forms, with or without
10     modification, are permitted provided that the following conditions are met:
11
12     * Redistributions of source code must retain the above copyright notice, this
13       list of conditions and the following disclaimer.
14
15     * Redistributions in binary form must reproduce the above copyright notice,
16       this list of conditions and the following disclaimer in the documentation
17       and/or other materials provided with the distribution.
18
19     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23     FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27     OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #ifndef CDSLIB_ALGO_BIT_REVERSAL_H
32 #define CDSLIB_ALGO_BIT_REVERSAL_H
33
34 #include <cds/algo/base.h>
35
36     // Source: http://stackoverflow.com/questions/746171/best-algorithm-for-bit-reversal-from-msb-lsb-to-lsb-msb-in-c
37 namespace cds { namespace algo {
38
39     /// Bit reversal algorithms
40     namespace bit_reversal {
41
42         /// SWAR algorithm (source: http://aggregate.org/MAGIC/#Bit%20Reversal)
43         struct swar {
44             /// 32bit
45             uint32_t operator()( uint32_t x ) const
46             {
47                 x = ( ( ( x & 0xaaaaaaaa ) >> 1 ) | ( ( x & 0x55555555 ) << 1 ));
48                 x = ( ( ( x & 0xcccccccc ) >> 2 ) | ( ( x & 0x33333333 ) << 2 ));
49                 x = ( ( ( x & 0xf0f0f0f0 ) >> 4 ) | ( ( x & 0x0f0f0f0f ) << 4 ));
50                 x = ( ( ( x & 0xff00ff00 ) >> 8 ) | ( ( x & 0x00ff00ff ) << 8 ));
51                 return( ( x >> 16 ) | ( x << 16 ));
52             }
53
54             /// 64bit
55             uint64_t operator()( uint64_t x ) const
56             {
57                 return ( static_cast<uint64_t>( operator()( static_cast<uint32_t>( x )) ) << 32 )  // low 32bit
58                     | ( static_cast<uint64_t>( operator()( static_cast<uint32_t>( x >> 32 )) ));  // high 32bit
59             }
60         };
61
62         /// Lookup table algorithm
63         struct lookup {
64             /// 32bit
65             uint32_t operator()( uint32_t x ) const
66             {
67                 static uint8_t const table[] = {
68                     0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
69                     0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
70                     0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
71                     0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
72                     0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
73                     0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
74                     0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
75                     0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
76                     0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
77                     0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
78                     0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
79                     0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
80                     0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
81                     0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
82                     0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
83                     0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
84                 };
85                 static_assert( sizeof( table ) / sizeof( table[0] ) == 256, "Table size mismatch" );
86
87                 return ( static_cast<uint32_t>( table[x & 0xff] ) << 24 ) |
88                     ( static_cast<uint32_t>( table[( x >> 8 ) & 0xff] ) << 16 ) |
89                     ( static_cast<uint32_t>( table[( x >> 16 ) & 0xff] ) << 8 ) |
90                     ( static_cast<uint32_t>( table[( x >> 24 ) & 0xff] ));
91             }
92
93             /// 64bit
94             uint64_t operator()( uint64_t x ) const
95             {
96                 return ( static_cast<uint64_t>( operator()( static_cast<uint32_t>( x )) ) << 32 ) |
97                     static_cast<uint64_t>( operator()( static_cast<uint32_t>( x >> 32 )) );
98             }
99         };
100
101
102         /// Mul-Div algorithm for 32bit architectire
103
104         /// Mul-Div algorithm
105         struct muldiv {
106             //@cond
107             static uint8_t muldiv32_byte( uint8_t b )
108             {
109                 return static_cast<uint8_t>( ( ( b * 0x0802LU & 0x22110LU ) | ( b * 0x8020LU & 0x88440LU )) * 0x10101LU >> 16 );
110             }
111
112             static uint8_t muldiv64_byte( uint8_t b )
113             {
114                 return static_cast<uint8_t>( ( b * 0x0202020202ULL & 0x010884422010ULL ) % 1023 );
115             }
116
117             // for 32bit architecture
118             static uint32_t muldiv32( uint32_t x )
119             {
120                 return static_cast<uint32_t>( muldiv32_byte( static_cast<uint8_t>( x >> 24 )) )
121                     | ( static_cast<uint32_t>( muldiv32_byte( static_cast<uint8_t>( x >> 16 )) ) << 8 )
122                     | ( static_cast<uint32_t>( muldiv32_byte( static_cast<uint8_t>( x >> 8 )) ) << 16 )
123                     | ( static_cast<uint32_t>( muldiv32_byte( static_cast<uint8_t>( x )) ) << 24 );
124             }
125
126             static uint64_t muldiv32( uint64_t x )
127             {
128                 return static_cast<uint64_t>( muldiv32_byte( static_cast<uint8_t>( x >> 56 )) )
129                     | ( static_cast<uint64_t>( muldiv32_byte( static_cast<uint8_t>( x >> 48 )) ) << 8 )
130                     | ( static_cast<uint64_t>( muldiv32_byte( static_cast<uint8_t>( x >> 40 )) ) << 16 )
131                     | ( static_cast<uint64_t>( muldiv32_byte( static_cast<uint8_t>( x >> 32 )) ) << 24 )
132                     | ( static_cast<uint64_t>( muldiv32_byte( static_cast<uint8_t>( x >> 24 )) ) << 32 )
133                     | ( static_cast<uint64_t>( muldiv32_byte( static_cast<uint8_t>( x >> 16 )) ) << 40 )
134                     | ( static_cast<uint64_t>( muldiv32_byte( static_cast<uint8_t>( x >> 8 )) ) << 48 )
135                     | ( static_cast<uint64_t>( muldiv32_byte( static_cast<uint8_t>( x )) ) << 56 );
136             }
137
138             /// for 64bit architectire
139             static uint32_t muldiv64( uint32_t x )
140             {
141                 return static_cast<uint32_t>( muldiv64_byte( static_cast<uint8_t>( x >> 24 )) )
142                     | ( static_cast<uint32_t>( muldiv64_byte( static_cast<uint8_t>( x >> 16 )) ) << 8 )
143                     | ( static_cast<uint32_t>( muldiv64_byte( static_cast<uint8_t>( x >> 8 )) ) << 16 )
144                     | ( static_cast<uint32_t>( muldiv64_byte( static_cast<uint8_t>( x )) ) << 24 );
145             }
146
147             static uint64_t muldiv64( uint64_t x )
148             {
149                 return static_cast<uint64_t>( muldiv64_byte( static_cast<uint8_t>( x >> 56 )) )
150                     | ( static_cast<uint64_t>( muldiv64_byte( static_cast<uint8_t>( x >> 48 )) ) << 8 )
151                     | ( static_cast<uint64_t>( muldiv64_byte( static_cast<uint8_t>( x >> 40 )) ) << 16 )
152                     | ( static_cast<uint64_t>( muldiv64_byte( static_cast<uint8_t>( x >> 32 )) ) << 24 )
153                     | ( static_cast<uint64_t>( muldiv64_byte( static_cast<uint8_t>( x >> 24 )) ) << 32 )
154                     | ( static_cast<uint64_t>( muldiv64_byte( static_cast<uint8_t>( x >> 16 )) ) << 40 )
155                     | ( static_cast<uint64_t>( muldiv64_byte( static_cast<uint8_t>( x >> 8 )) ) << 48 )
156                     | ( static_cast<uint64_t>( muldiv64_byte( static_cast<uint8_t>( x )) ) << 56 );
157             }
158             //@endcond
159
160             /// 32bit
161             uint32_t operator()( uint32_t x ) const
162             {
163 #           if CDS_BUILD_BITS == 32
164                 return muldiv32( x );
165 #           else
166                 return muldiv64( x );
167 #           endif
168             }
169
170             /// 64bit
171             uint64_t operator()( uint64_t x ) const
172             {
173 #           if CDS_BUILD_BITS == 32
174                 return muldiv32( x );
175 #           else
176                 return muldiv64( x );
177 #           endif
178             }
179         };
180
181     } // namespace bit_reversal
182 }} // namespace cds::algo
183
184 #endif // #ifndef CDSLIB_ALGO_BIT_REVERSAL_H