interleave.h 1.58 KB
Newer Older
Martin Schläffer committed
1 2 3 4 5
#ifndef INTERLEAVE_H_
#define INTERLEAVE_H_

#include <stdint.h>

Martin Schläffer committed
6 7
#include "config.h"
#include "endian.h"
Enrico Pozzobon committed
8 9
#include "forceinline.h"

Martin Schläffer committed
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
#if ASCON_INLINE_BI

#define TOBI deinterleave32
#define FROMBI interleave32

#else

uint64_t TOBI(uint64_t in);
uint64_t FROMBI(uint64_t in);

#endif

extern const uint32_t B[3];

forceinline uint32_t deinterleave16(uint32_t x) {
Martin Schläffer committed
25
  uint32_t t;
Martin Schläffer committed
26 27 28 29
  t = (x ^ (x >> 1)) & B[0], x ^= t ^ (t << 1);
  t = (x ^ (x >> 2)) & B[1], x ^= t ^ (t << 2);
  t = (x ^ (x >> 4)) & B[2], x ^= t ^ (t << 4);
  t = (x ^ (x >> 8)) & 0xff00, x ^= t ^ (t << 8);
Martin Schläffer committed
30 31 32
  return x;
}

Martin Schläffer committed
33
forceinline uint32_t interleave16(uint32_t x) {
Martin Schläffer committed
34
  uint32_t t;
Martin Schläffer committed
35 36 37 38
  t = (x ^ (x >> 8)) & 0xff00, x ^= t ^ (t << 8);
  t = (x ^ (x >> 4)) & B[2], x ^= t ^ (t << 4);
  t = (x ^ (x >> 2)) & B[1], x ^= t ^ (t << 2);
  t = (x ^ (x >> 1)) & B[0], x ^= t ^ (t << 1);
Martin Schläffer committed
39 40 41 42
  return x;
}

/* credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 */
Enrico Pozzobon committed
43
forceinline uint64_t deinterleave32(uint64_t in) {
Martin Schläffer committed
44
  in = U64BIG(in);
Martin Schläffer committed
45 46
  uint32_t hi = in >> 32;
  uint32_t lo = in;
Martin Schläffer committed
47 48 49 50 51 52
  uint32_t t0, t1, e, o;
  t0 = deinterleave16(lo);
  t1 = deinterleave16(hi);
  e = (t1 << 16) | (t0 & 0x0000FFFF);
  o = (t1 & 0xFFFF0000) | (t0 >> 16);
  return (uint64_t)o << 32 | e;
Martin Schläffer committed
53 54 55
}

/* credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 */
Enrico Pozzobon committed
56
forceinline uint64_t interleave32(uint64_t in) {
Martin Schläffer committed
57 58 59 60 61 62 63 64
  uint32_t e = in;
  uint32_t o = in >> 32;
  uint32_t t0, t1, lo, hi;
  t0 = (o << 16) | (e & 0x0000FFFF);
  t1 = (o & 0xFFFF0000) | (e >> 16);
  lo = interleave16(t0);
  hi = interleave16(t1);
  return U64BIG((uint64_t)hi << 32 | lo);
Martin Schläffer committed
65 66 67
}

#endif /* INTERLEAVE_H_ */