Botan  1.11.15
src/lib/utils/donna128.h
Go to the documentation of this file.
00001 /*
00002 * A minimal 128-bit integer type for curve25519-donna
00003 * (C) 2014 Jack Lloyd
00004 *
00005 * Botan is released under the Simplified BSD License (see license.txt)
00006 */
00007 
00008 #ifndef BOTAN_CURVE25519_DONNA128_H__
00009 #define BOTAN_CURVE25519_DONNA128_H__
00010 
00011 #include <botan/mul128.h>
00012 
00013 namespace Botan {
00014 
00015 class donna128
00016    {
00017    public:
00018       donna128(u64bit ll = 0, u64bit hh = 0) { l = ll; h = hh; }
00019 
00020       donna128(const donna128&) = default;
00021       donna128& operator=(const donna128&) = default;
00022 
00023       friend donna128 operator>>(const donna128& x, size_t shift)
00024          {
00025          donna128 z = x;
00026          const u64bit carry = z.h << (64 - shift);
00027          z.h = (z.h >> shift);
00028          z.l = (z.l >> shift) | carry;
00029          return z;
00030          }
00031 
00032       friend donna128 operator<<(const donna128& x, size_t shift)
00033          {
00034          donna128 z = x;
00035          const u64bit carry = z.l >> (64 - shift);
00036          z.l = (z.l << shift);
00037          z.h = (z.h << shift) | carry;
00038          return z;
00039          }
00040 
00041       friend u64bit operator&(const donna128& x, u64bit mask)
00042          {
00043          return x.l & mask;
00044          }
00045 
00046       u64bit operator&=(u64bit mask)
00047          {
00048          h = 0;
00049          l &= mask;
00050          return l;
00051          }
00052 
00053       donna128& operator+=(const donna128& x)
00054          {
00055          l += x.l;
00056          h += (l < x.l);
00057          h += x.h;
00058          return *this;
00059          }
00060 
00061       donna128& operator+=(u64bit x)
00062          {
00063          l += x;
00064          h += (l < x);
00065          return *this;
00066          }
00067 
00068       u64bit lo() const { return l; }
00069       u64bit hi() const { return h; }
00070    private:
00071       u64bit h = 0, l = 0;
00072    };
00073 
00074 inline donna128 operator*(const donna128& x, u64bit y)
00075    {
00076    BOTAN_ASSERT(x.hi() == 0, "High 64 bits of donna128 set to zero during multiply");
00077 
00078    u64bit lo = 0, hi = 0;
00079    mul64x64_128(x.lo(), y, &lo, &hi);
00080    return donna128(lo, hi);
00081    }
00082 
00083 inline donna128 operator+(const donna128& x, const donna128& y)
00084    {
00085    donna128 z = x;
00086    z += y;
00087    return z;
00088    }
00089 
00090 inline donna128 operator+(const donna128& x, u64bit y)
00091    {
00092    donna128 z = x;
00093    z += y;
00094    return z;
00095    }
00096 
00097 inline donna128 operator|(const donna128& x, const donna128& y)
00098    {
00099    return donna128(x.lo() | y.lo(), x.hi() | y.hi());
00100    }
00101 
00102 inline u64bit carry_shift(const donna128& a, size_t shift)
00103    {
00104    return (a >> shift).lo();
00105    }
00106 
00107 inline u64bit combine_lower(const donna128 a, size_t s1,
00108                             const donna128 b, size_t s2)
00109    {
00110    donna128 z = (a >> s1) | (b << s2);
00111    return z.lo();
00112    }
00113 
00114 #if defined(BOTAN_TARGET_HAS_NATIVE_UINT128)
00115 inline u64bit carry_shift(const uint128_t a, size_t shift)
00116    {
00117    return static_cast<u64bit>(a >> shift);
00118    }
00119 
00120 inline u64bit combine_lower(const uint128_t a, size_t s1,
00121                             const uint128_t b, size_t s2)
00122    {
00123    return static_cast<u64bit>((a >> s1) | (b << s2));
00124    }
00125 #endif
00126 
00127 }
00128 
00129 #endif