1 /**
2  * This module contains a collection of bit-level operations.
3  *
4  * Copyright:
5  *     Public Domain
6  *     Some parts copyright (c) 2009-2016 dunnhumby Germany GmbH.
7  *     All rights reserved.
8  *
9  * License:
10  *     Tango Dual License: 3-Clause BSD License / Academic Free License v3.0.
11  *     See LICENSE_TANGO.txt for details.
12  *
13  * Authors: Sean Kelly
14  *
15  */
16 module ocean.core.BitManip;
17 
18 public import core.bitop;
19 
20 version (unittest) import ocean.core.Test;
21 
22 /**
23  * Reverses the order of bits in a 64-bit integer.
24  */
25 ulong bitswap ( ulong x )
26 {
27     version( D_InlineAsm_X86_64 )
28     {
29         asm
30         {
31             // Author: Tiago Gasiba.
32             mov RAX, x;
33             mov RDX, RAX;
34             shr RAX, 1;
35             mov RCX, 0x5555_5555_5555_5555L;
36             and RDX, RCX;
37             and RAX, RCX;
38             shl RDX, 1;
39             or  RAX, RDX;
40 
41             mov RDX, RAX;
42             shr RAX, 2;
43             mov RCX, 0x3333_3333_3333_3333L;
44             and RDX, RCX;
45             and RAX, RCX;
46             shl RDX, 2;
47             or  RAX, RDX;
48 
49             mov RDX, RAX;
50             shr RAX, 4;
51             mov RCX, 0x0f0f_0f0f_0f0f_0f0fL;
52             and RDX, RCX;
53             and RAX, RCX;
54             shl RDX, 4;
55             or  RAX, RDX;
56             bswap RAX;
57         }
58     }
59     else
60     {
61         // swap odd and even bits
62         x = ((x >> 1) & 0x5555_5555_5555_5555L) | ((x & 0x5555_5555_5555_5555L) << 1);
63         // swap consecutive pairs
64         x = ((x >> 2) & 0x3333_3333_3333_3333L) | ((x & 0x3333_3333_3333_3333L) << 2);
65         // swap nibbles
66         x = ((x >> 4) & 0x0f0f_0f0f_0f0f_0f0fL) | ((x & 0x0f0f_0f0f_0f0f_0f0fL) << 4);
67         // swap bytes
68         x = ((x >> 8) & 0x00FF_00FF_00FF_00FFL) | ((x & 0x00FF_00FF_00FF_00FFL) << 8);
69         // swap shorts
70         x = ((x >> 16) & 0x0000_FFFF_0000_FFFFL) | ((x & 0x0000_FFFF_0000_FFFFL) << 16);
71         // swap ints
72         x = ( x >> 32              ) | ( x               << 32);
73         return x;
74     }
75 }
76 
77 unittest
78 {
79     test( bitswap( 0b1000000000000000000000010000000000000000100000000000000000000001 )
80             == 0b1000000000000000000000010000000000000000100000000000000000000001 );
81     test( bitswap( 0b1110000000000000000000010000000000000000100000000000000000000001 )
82             == 0b1000000000000000000000010000000000000000100000000000000000000111 );
83 }