Botan  1.11.15
src/lib/utils/simd/simd_scalar/simd_scalar.h
Go to the documentation of this file.
00001 /*
00002 * Scalar emulation of SIMD
00003 * (C) 2009,2013 Jack Lloyd
00004 *
00005 * Botan is released under the Simplified BSD License (see license.txt)
00006 */
00007 
00008 #ifndef BOTAN_SIMD_SCALAR_H__
00009 #define BOTAN_SIMD_SCALAR_H__
00010 
00011 #include <botan/loadstor.h>
00012 #include <botan/bswap.h>
00013 
00014 namespace Botan {
00015 
00016 /**
00017 * Fake SIMD, using plain scalar operations
00018 * Often still faster than iterative on superscalar machines
00019 */
00020 template<typename T, size_t N>
00021 class SIMD_Scalar
00022    {
00023    public:
00024       static bool enabled() { return true; }
00025 
00026       static size_t size() { return N; }
00027 
00028       SIMD_Scalar() { /* uninitialized */ }
00029 
00030       SIMD_Scalar(const T B[N])
00031          {
00032          for(size_t i = 0; i != size(); ++i)
00033             m_v[i] = B[i];
00034          }
00035 
00036       SIMD_Scalar(T B)
00037          {
00038          for(size_t i = 0; i != size(); ++i)
00039             m_v[i] = B;
00040          }
00041 
00042       static SIMD_Scalar<T,N> load_le(const void* in)
00043          {
00044          SIMD_Scalar<T,N> out;
00045          const byte* in_b = static_cast<const byte*>(in);
00046 
00047          for(size_t i = 0; i != size(); ++i)
00048             out.m_v[i] = Botan::load_le<T>(in_b, i);
00049 
00050          return out;
00051          }
00052 
00053       static SIMD_Scalar<T,N> load_be(const void* in)
00054          {
00055          SIMD_Scalar<T,N> out;
00056          const byte* in_b = static_cast<const byte*>(in);
00057 
00058          for(size_t i = 0; i != size(); ++i)
00059             out.m_v[i] = Botan::load_be<T>(in_b, i);
00060 
00061          return out;
00062          }
00063 
00064       void store_le(byte out[]) const
00065          {
00066          for(size_t i = 0; i != size(); ++i)
00067             Botan::store_le(m_v[i], out + i*sizeof(T));
00068          }
00069 
00070       void store_be(byte out[]) const
00071          {
00072          for(size_t i = 0; i != size(); ++i)
00073             Botan::store_be(m_v[i], out + i*sizeof(T));
00074          }
00075 
00076       void rotate_left(size_t rot)
00077          {
00078          for(size_t i = 0; i != size(); ++i)
00079             m_v[i] = Botan::rotate_left(m_v[i], rot);
00080          }
00081 
00082       void rotate_right(size_t rot)
00083          {
00084          for(size_t i = 0; i != size(); ++i)
00085             m_v[i] = Botan::rotate_right(m_v[i], rot);
00086          }
00087 
00088       void operator+=(const SIMD_Scalar<T,N>& other)
00089          {
00090          for(size_t i = 0; i != size(); ++i)
00091             m_v[i] += other.m_v[i];
00092          }
00093 
00094       void operator-=(const SIMD_Scalar<T,N>& other)
00095          {
00096          for(size_t i = 0; i != size(); ++i)
00097             m_v[i] -= other.m_v[i];
00098          }
00099 
00100       SIMD_Scalar<T,N> operator+(const SIMD_Scalar<T,N>& other) const
00101          {
00102          SIMD_Scalar<T,N> out = *this;
00103          out += other;
00104          return out;
00105          }
00106 
00107       SIMD_Scalar<T,N> operator-(const SIMD_Scalar<T,N>& other) const
00108          {
00109          SIMD_Scalar<T,N> out = *this;
00110          out -= other;
00111          return out;
00112          }
00113 
00114       void operator^=(const SIMD_Scalar<T,N>& other)
00115          {
00116          for(size_t i = 0; i != size(); ++i)
00117             m_v[i] ^= other.m_v[i];
00118          }
00119 
00120       SIMD_Scalar<T,N> operator^(const SIMD_Scalar<T,N>& other) const
00121          {
00122          SIMD_Scalar<T,N> out = *this;
00123          out ^= other;
00124          return out;
00125          }
00126 
00127       void operator|=(const SIMD_Scalar<T,N>& other)
00128          {
00129          for(size_t i = 0; i != size(); ++i)
00130             m_v[i] |= other.m_v[i];
00131          }
00132 
00133       void operator&=(const SIMD_Scalar<T,N>& other)
00134          {
00135          for(size_t i = 0; i != size(); ++i)
00136             m_v[i] &= other.m_v[i];
00137          }
00138 
00139       SIMD_Scalar<T,N> operator&(const SIMD_Scalar<T,N>& other)
00140          {
00141          SIMD_Scalar<T,N> out = *this;
00142          out &= other;
00143          return out;
00144          }
00145 
00146       SIMD_Scalar<T,N> operator<<(size_t shift) const
00147          {
00148          SIMD_Scalar<T,N> out = *this;
00149          for(size_t i = 0; i != size(); ++i)
00150             out.m_v[i] <<= shift;
00151          return out;
00152          }
00153 
00154       SIMD_Scalar<T,N> operator>>(size_t shift) const
00155          {
00156          SIMD_Scalar<T,N> out = *this;
00157          for(size_t i = 0; i != size(); ++i)
00158             out.m_v[i] >>= shift;
00159          return out;
00160          }
00161 
00162       SIMD_Scalar<T,N> operator~() const
00163          {
00164          SIMD_Scalar<T,N> out = *this;
00165          for(size_t i = 0; i != size(); ++i)
00166             out.m_v[i] = ~out.m_v[i];
00167          return out;
00168          }
00169 
00170       // (~reg) & other
00171       SIMD_Scalar<T,N> andc(const SIMD_Scalar<T,N>& other)
00172          {
00173          SIMD_Scalar<T,N> out;
00174          for(size_t i = 0; i != size(); ++i)
00175             out.m_v[i] = (~m_v[i]) & other.m_v[i];
00176          return out;
00177          }
00178 
00179       SIMD_Scalar<T,N> bswap() const
00180          {
00181          SIMD_Scalar<T,N> out;
00182          for(size_t i = 0; i != size(); ++i)
00183             out.m_v[i] = reverse_bytes(m_v[i]);
00184          return out;
00185          }
00186 
00187       static void transpose(SIMD_Scalar<T,N>& B0, SIMD_Scalar<T,N>& B1,
00188                             SIMD_Scalar<T,N>& B2, SIMD_Scalar<T,N>& B3)
00189          {
00190          static_assert(N == 4, "4x4 transpose");
00191          SIMD_Scalar<T,N> T0({B0.m_v[0], B1.m_v[0], B2.m_v[0], B3.m_v[0]});
00192          SIMD_Scalar<T,N> T1({B0.m_v[1], B1.m_v[1], B2.m_v[1], B3.m_v[1]});
00193          SIMD_Scalar<T,N> T2({B0.m_v[2], B1.m_v[2], B2.m_v[2], B3.m_v[2]});
00194          SIMD_Scalar<T,N> T3({B0.m_v[3], B1.m_v[3], B2.m_v[3], B3.m_v[3]});
00195 
00196          B0 = T0;
00197          B1 = T1;
00198          B2 = T2;
00199          B3 = T3;
00200          }
00201 
00202    private:
00203       SIMD_Scalar(std::initializer_list<T> B)
00204          {
00205          size_t i = 0;
00206          for(auto v = B.begin(); v != B.end(); ++v)
00207             m_v[i++] = *v;
00208          }
00209 
00210       T m_v[N];
00211    };
00212 
00213 }
00214 
00215 #endif