Skip to content

Instantly share code, notes, and snippets.

@oyvindln
Last active July 20, 2017 11:55
Show Gist options
  • Save oyvindln/cc65fc6c479d3347708be972798d49f7 to your computer and use it in GitHub Desktop.
Save oyvindln/cc65fc6c479d3347708be972798d49f7 to your computer and use it in GitHub Desktop.
cpp version
#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