SkNx.h revision a156a8ffbe1342a9c329e66ad1438934ac309d70
1/* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#ifndef SkNx_DEFINED 9#define SkNx_DEFINED 10 11 12#define SKNX_NO_SIMDx // Remove the x to disable SIMD for all SkNx types. 13 14 15#include "SkScalar.h" 16#include "SkTypes.h" 17#include <math.h> 18#define REQUIRE(x) static_assert(x, #x) 19 20// The default implementations of SkNi<N,T> and SkNf<N,T> just fall back on a pair of size N/2. 21template <int N, typename T> 22class SkNi { 23public: 24 // For now SkNi is a _very_ minimal sketch just to support comparison operators on SkNf. 25 SkNi() {} 26 SkNi(const SkNi<N/2, T>& lo, const SkNi<N/2, T>& hi) : fLo(lo), fHi(hi) {} 27 bool allTrue() const { return fLo.allTrue() && fHi.allTrue(); } 28 bool anyTrue() const { return fLo.anyTrue() || fHi.anyTrue(); } 29 30private: 31 REQUIRE(0 == (N & (N-1))); 32 SkNi<N/2, T> fLo, fHi; 33}; 34 35template <int N, typename T> 36class SkNf { 37 static SkNi<N,int32_t> ToNi(float); 38 static SkNi<N,int64_t> ToNi(double); 39 typedef decltype(ToNi(T())) Ni; 40public: 41 SkNf() {} 42 explicit SkNf(T val) : fLo(val), fHi(val) {} 43 static SkNf Load(const T vals[N]) { 44 return SkNf(SkNf<N/2,T>::Load(vals), SkNf<N/2,T>::Load(vals+N/2)); 45 } 46 47 SkNf(T a, T b) : fLo(a), fHi(b) { REQUIRE(N==2); } 48 SkNf(T a, T b, T c, T d) : fLo(a,b), fHi(c,d) { REQUIRE(N==4); } 49 SkNf(T a, T b, T c, T d, T e, T f, T g, T h) : fLo(a,b,c,d), fHi(e,f,g,h) { REQUIRE(N==8); } 50 51 void store(T vals[N]) const { 52 fLo.store(vals); 53 fHi.store(vals+N/2); 54 } 55 56 SkNf operator + (const SkNf& o) const { return SkNf(fLo + o.fLo, fHi + o.fHi); } 57 SkNf operator - (const SkNf& o) const { return SkNf(fLo - o.fLo, fHi - o.fHi); } 58 SkNf operator * (const SkNf& o) const { return SkNf(fLo * o.fLo, fHi * o.fHi); } 59 SkNf operator / (const SkNf& o) const { return SkNf(fLo / o.fLo, fHi / o.fHi); } 60 61 Ni operator == (const SkNf& o) const { return Ni(fLo == o.fLo, fHi == o.fHi); } 62 Ni operator != (const SkNf& o) const { return Ni(fLo != o.fLo, fHi != o.fHi); } 63 Ni operator < (const SkNf& o) const { return Ni(fLo < o.fLo, fHi < o.fHi); } 64 Ni operator > (const SkNf& o) const { return Ni(fLo > o.fLo, fHi > o.fHi); } 65 Ni operator <= (const SkNf& o) const { return Ni(fLo <= o.fLo, fHi <= o.fHi); } 66 Ni operator >= (const SkNf& o) const { return Ni(fLo >= o.fLo, fHi >= o.fHi); } 67 68 static SkNf Min(const SkNf& l, const SkNf& r) { 69 return SkNf(SkNf<N/2,T>::Min(l.fLo, r.fLo), SkNf<N/2,T>::Min(l.fHi, r.fHi)); 70 } 71 static SkNf Max(const SkNf& l, const SkNf& r) { 72 return SkNf(SkNf<N/2,T>::Max(l.fLo, r.fLo), SkNf<N/2,T>::Max(l.fHi, r.fHi)); 73 } 74 75 SkNf sqrt() const { return SkNf(fLo. sqrt(), fHi. sqrt()); } 76 SkNf rsqrt() const { return SkNf(fLo.rsqrt(), fHi.rsqrt()); } 77 78 SkNf invert() const { return SkNf(fLo. invert(), fHi. invert()); } 79 SkNf approxInvert() const { return SkNf(fLo.approxInvert(), fHi.approxInvert()); } 80 81 template <int k> T kth() const { 82 SkASSERT(0 <= k && k < N); 83 return k < N/2 ? fLo.template kth<k>() : fHi.template kth<k-N/2>(); 84 } 85 86private: 87 REQUIRE(0 == (N & (N-1))); 88 SkNf(const SkNf<N/2, T>& lo, const SkNf<N/2, T>& hi) : fLo(lo), fHi(hi) {} 89 90 SkNf<N/2, T> fLo, fHi; 91}; 92 93 94// Bottom out the default implementation with scalars when nothing's been specialized. 95template <typename T> 96class SkNi<1,T> { 97public: 98 SkNi() {} 99 explicit SkNi(T val) : fVal(val) {} 100 bool allTrue() const { return (bool)fVal; } 101 bool anyTrue() const { return (bool)fVal; } 102 103private: 104 T fVal; 105}; 106 107template <typename T> 108class SkNf<1,T> { 109 static SkNi<1,int32_t> ToNi(float); 110 static SkNi<1,int64_t> ToNi(double); 111 typedef decltype(ToNi(T())) Ni; 112public: 113 SkNf() {} 114 explicit SkNf(T val) : fVal(val) {} 115 static SkNf Load(const T vals[1]) { return SkNf(vals[0]); } 116 117 void store(T vals[1]) const { vals[0] = fVal; } 118 119 SkNf operator + (const SkNf& o) const { return SkNf(fVal + o.fVal); } 120 SkNf operator - (const SkNf& o) const { return SkNf(fVal - o.fVal); } 121 SkNf operator * (const SkNf& o) const { return SkNf(fVal * o.fVal); } 122 SkNf operator / (const SkNf& o) const { return SkNf(fVal / o.fVal); } 123 124 Ni operator == (const SkNf& o) const { return Ni(fVal == o.fVal); } 125 Ni operator != (const SkNf& o) const { return Ni(fVal != o.fVal); } 126 Ni operator < (const SkNf& o) const { return Ni(fVal < o.fVal); } 127 Ni operator > (const SkNf& o) const { return Ni(fVal > o.fVal); } 128 Ni operator <= (const SkNf& o) const { return Ni(fVal <= o.fVal); } 129 Ni operator >= (const SkNf& o) const { return Ni(fVal >= o.fVal); } 130 131 static SkNf Min(const SkNf& l, const SkNf& r) { return SkNf(SkTMin(l.fVal, r.fVal)); } 132 static SkNf Max(const SkNf& l, const SkNf& r) { return SkNf(SkTMax(l.fVal, r.fVal)); } 133 134 SkNf sqrt() const { return SkNf(Sqrt(fVal)); } 135 SkNf rsqrt() const { return SkNf((T)1 / Sqrt(fVal)); } 136 137 SkNf invert() const { return SkNf((T)1 / fVal); } 138 SkNf approxInvert() const { return this->invert(); } 139 140 template <int k> T kth() const { 141 SkASSERT(k == 0); 142 return fVal; 143 } 144 145private: 146 // We do double sqrts natively, or via floats for any other type. 147 template <typename U> 148 static U Sqrt(U val) { return (U) ::sqrtf((float)val); } 149 static double Sqrt(double val) { return ::sqrt ( val); } 150 151 T fVal; 152}; 153 154 155// Generic syntax sugar that should work equally well for all SkNi and SkNf implementations. 156template <typename SkNx> SkNx operator - (const SkNx& l) { return SkNx(0) - l; } 157 158template <typename SkNx> SkNx& operator += (SkNx& l, const SkNx& r) { return (l = l + r); } 159template <typename SkNx> SkNx& operator -= (SkNx& l, const SkNx& r) { return (l = l - r); } 160template <typename SkNx> SkNx& operator *= (SkNx& l, const SkNx& r) { return (l = l * r); } 161template <typename SkNx> SkNx& operator /= (SkNx& l, const SkNx& r) { return (l = l / r); } 162 163 164// Include platform specific specializations if available. 165#ifndef SKNX_NO_SIMD 166 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 167 #include "../opts/SkNx_sse.h" 168 #elif defined(SK_ARM_HAS_NEON) 169 #include "../opts/SkNx_neon.h" 170 #endif 171#endif 172 173#undef REQUIRE 174 175typedef SkNf<2, float> Sk2f; 176typedef SkNf<2, double> Sk2d; 177typedef SkNf<2, SkScalar> Sk2s; 178 179typedef SkNf<4, float> Sk4f; 180typedef SkNf<4, double> Sk4d; 181typedef SkNf<4, SkScalar> Sk4s; 182 183typedef SkNi<4, int32_t> Sk4i; 184 185#endif//SkNx_DEFINED 186