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 }