Last active
July 20, 2017 11:55
-
-
Save oyvindln/cc65fc6c479d3347708be972798d49f7 to your computer and use it in GitHub Desktop.
cpp version
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdint.h> | |
#include <initializer_list> | |
typedef uint64_t u64; | |
typedef uint32_t u32; | |
typedef std::size_t usize; | |
const u32 SHIFT_MASK = (1 << 6) - 1; | |
// Putting these in an anonymous namespace makes them internal to this compilation unit, similar | |
// to a non-pub function in rust. | |
namespace { | |
template <typename T> T wrapping_sub(T lhs, T rhs) { | |
return lhs - rhs; | |
} | |
template <typename T> T wrapping_add(T lhs, T rhs) { | |
return lhs + rhs; | |
} | |
// These are marked #[inline(always)] in rust. | |
template <typename T> __attribute__((always_inline)) T wrapping_shl(T lhs, u32 rhs) { | |
// 64 is the number of bits in the type, | |
// which in the rust version | |
// will be different for other types. | |
return lhs << static_cast<T>(rhs & (64 - 1)); | |
} | |
template <typename T> __attribute__((always_inline)) T wrapping_shr(T lhs, u32 rhs) { | |
return lhs >> static_cast<T>(rhs & (64 - 1)); | |
} | |
} | |
template <class T> | |
class w { | |
T t; | |
public: | |
// The methods in Wrapping are defined as #[inline(always)] in rust, | |
// to get the equivialent in c++ we have to use a compiler attribute. | |
__attribute__((always_inline)) inline w (T t): t(t) { } | |
__attribute__((always_inline)) friend w<T> operator+(w<T> lhs, w<T> rhs) { | |
// add and sub are implemented through wrapping_add in rust, so we do the same | |
// here. | |
// Additionally, the rust version returns a new value rather than re-using | |
// lhs, so we do the same here. (This increases the number of allocas a bit.) | |
return w(wrapping_add(lhs.t, rhs.t)); | |
} | |
__attribute__((always_inline)) friend w<T> operator-(w<T> lhs, w<T> rhs) { | |
return w(wrapping_sub(lhs.t, rhs.t)); | |
} | |
__attribute__((always_inline)) friend w<T> operator^(w<T> lhs, w<T> rhs) { | |
return w(lhs.t ^ rhs.t); | |
} | |
__attribute__((always_inline)) friend w<T> operator<<(w<T> lhs, usize other) { | |
return w(wrapping_shl(lhs.t, static_cast<u32>(other & static_cast<usize>(SHIFT_MASK)))); | |
} | |
__attribute__((always_inline)) friend w<T> operator>>(w<T> lhs, usize other) { | |
return w(wrapping_shr(lhs.t, static_cast<u32>(other & static_cast<usize>(SHIFT_MASK)))); | |
} | |
}; | |
extern "C" | |
void foo() { | |
auto a = w<u64>(0x9e3779b97f4a7c13); | |
auto b = w<u64>(0x9e3779b97f4a7c13); | |
auto c = w<u64>(0x9e3779b97f4a7c13); | |
auto d = w<u64>(0x9e3779b97f4a7c13); | |
auto e = w<u64>(0x9e3779b97f4a7c13); | |
auto f = w<u64>(0x9e3779b97f4a7c13); | |
auto g = w<u64>(0x9e3779b97f4a7c13); | |
auto h = w<u64>(0x9e3779b97f4a7c13); | |
for (int n : {0, 1, 2, 3}) { | |
a=a-e; f=f^(h>>9); h=h+a; | |
b=b-f; g=g^(a<<9); a=a+b; | |
c=c-g; h=h^(b>>23); b=b+c; | |
d=d-h; a=a^(c<<15); c=c+d; | |
e=e-a; b=b^(d>>14); d=d+e; | |
f=f-b; c=c^(e<<20); e=e+f; | |
g=g-c; d=d^(f>>17); f=f+g; | |
h=h-d; e=e^(g<<14); g=g+h; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment