| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #ifndef SkNx_DEFINED | 8 #ifndef SkNx_DEFINED |
| 9 #define SkNx_DEFINED | 9 #define SkNx_DEFINED |
| 10 | 10 |
| 11 | 11 |
| 12 #define SKNX_NO_SIMDx // Remove the x to disable SIMD for all SkNx types. | 12 #define SKNX_NO_SIMDx // Remove the x to disable SIMD for all SkNx types. |
| 13 | 13 |
| 14 | 14 |
| 15 #include "SkScalar.h" | 15 #include "SkScalar.h" |
| 16 #include "SkTypes.h" | 16 #include "SkTypes.h" |
| 17 #include <math.h> | 17 #include <math.h> |
| 18 #define REQUIRE(x) static_assert(x, #x) | 18 #define REQUIRE(x) static_assert(x, #x) |
| 19 | 19 |
| 20 // This file may be included multiple times by .cpp files with different flags,
leading | 20 // This file may be included multiple times by .cpp files with different flags,
leading |
| 21 // to different definitions. Usually that doesn't matter because it's all inlin
ed, but | 21 // to different definitions. Usually that doesn't matter because it's all inlin
ed, but |
| 22 // in Debug modes the compilers may not inline everything. So wrap everything i
n an | 22 // in Debug modes the compilers may not inline everything. So wrap everything i
n an |
| 23 // anonymous namespace to give each includer their own silo of this code (or the
linker | 23 // anonymous namespace to give each includer their own silo of this code (or the
linker |
| 24 // will probably pick one randomly for us, which is rarely correct). | 24 // will probably pick one randomly for us, which is rarely correct). |
| 25 namespace { | 25 namespace { |
| 26 | 26 |
| 27 // The default implementations just fall back on a pair of size N/2. | 27 // The default implementations just fall back on a pair of size N/2. |
| 28 | 28 |
| 29 // SkNb is a _very_ minimal class representing a vector of bools returned by com
parison operators. |
| 30 // We pass along the byte size of the compared types (Bytes) to help platform sp
ecializations. |
| 31 template <int N, int Bytes> |
| 32 class SkNb { |
| 33 public: |
| 34 SkNb() {} |
| 35 SkNb(const SkNb<N/2, Bytes>& lo, const SkNb<N/2, Bytes>& hi) : fLo(lo), fHi(
hi) {} |
| 36 |
| 37 bool allTrue() const { return fLo.allTrue() && fHi.allTrue(); } |
| 38 bool anyTrue() const { return fLo.anyTrue() || fHi.anyTrue(); } |
| 39 |
| 40 protected: |
| 41 REQUIRE(0 == (N & (N-1))); |
| 42 SkNb<N/2, Bytes> fLo, fHi; |
| 43 }; |
| 44 |
| 29 template <int N, typename T> | 45 template <int N, typename T> |
| 30 class SkNi { | 46 class SkNi { |
| 31 public: | 47 public: |
| 32 SkNi() {} | 48 SkNi() {} |
| 33 SkNi(const SkNi<N/2, T>& lo, const SkNi<N/2, T>& hi) : fLo(lo), fHi(hi) {} | 49 SkNi(const SkNi<N/2, T>& lo, const SkNi<N/2, T>& hi) : fLo(lo), fHi(hi) {} |
| 34 explicit SkNi(T val) : fLo(val), fHi(val) {} | 50 explicit SkNi(T val) : fLo(val), fHi(val) {} |
| 35 static SkNi Load(const T vals[N]) { | 51 static SkNi Load(const T vals[N]) { |
| 36 return SkNi(SkNi<N/2,T>::Load(vals), SkNi<N/2,T>::Load(vals+N/2)); | 52 return SkNi(SkNi<N/2,T>::Load(vals), SkNi<N/2,T>::Load(vals+N/2)); |
| 37 } | 53 } |
| 38 | 54 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 55 SkNi operator + (const SkNi& o) const { return SkNi(fLo + o.fLo, fHi + o.fHi
); } | 71 SkNi operator + (const SkNi& o) const { return SkNi(fLo + o.fLo, fHi + o.fHi
); } |
| 56 SkNi operator - (const SkNi& o) const { return SkNi(fLo - o.fLo, fHi - o.fHi
); } | 72 SkNi operator - (const SkNi& o) const { return SkNi(fLo - o.fLo, fHi - o.fHi
); } |
| 57 SkNi operator * (const SkNi& o) const { return SkNi(fLo * o.fLo, fHi * o.fHi
); } | 73 SkNi operator * (const SkNi& o) const { return SkNi(fLo * o.fLo, fHi * o.fHi
); } |
| 58 | 74 |
| 59 SkNi operator << (int bits) const { return SkNi(fLo << bits, fHi << bits); } | 75 SkNi operator << (int bits) const { return SkNi(fLo << bits, fHi << bits); } |
| 60 SkNi operator >> (int bits) const { return SkNi(fLo >> bits, fHi >> bits); } | 76 SkNi operator >> (int bits) const { return SkNi(fLo >> bits, fHi >> bits); } |
| 61 | 77 |
| 62 static SkNi Min(const SkNi& a, const SkNi& b) { | 78 static SkNi Min(const SkNi& a, const SkNi& b) { |
| 63 return SkNi(SkNi<N/2, T>::Min(a.fLo, b.fLo), SkNi<N/2, T>::Min(a.fHi, b.
fHi)); | 79 return SkNi(SkNi<N/2, T>::Min(a.fLo, b.fLo), SkNi<N/2, T>::Min(a.fHi, b.
fHi)); |
| 64 } | 80 } |
| 65 SkNi operator < (const SkNi& o) const { return SkNi(fLo < o.fLo, fHi < o.fHi
); } | 81 |
| 82 // TODO: comparisons, max? |
| 66 | 83 |
| 67 template <int k> T kth() const { | 84 template <int k> T kth() const { |
| 68 SkASSERT(0 <= k && k < N); | 85 SkASSERT(0 <= k && k < N); |
| 69 return k < N/2 ? fLo.template kth<k>() : fHi.template kth<k-N/2>(); | 86 return k < N/2 ? fLo.template kth<k>() : fHi.template kth<k-N/2>(); |
| 70 } | 87 } |
| 71 | 88 |
| 72 bool allTrue() const { return fLo.allTrue() && fHi.allTrue(); } | |
| 73 bool anyTrue() const { return fLo.anyTrue() || fHi.anyTrue(); } | |
| 74 SkNi thenElse(const SkNi& t, const SkNi& e) const { | |
| 75 return SkNi(fLo.thenElse(t.fLo, e.fLo), fHi.thenElse(t.fHi, e.fHi)); | |
| 76 } | |
| 77 | |
| 78 protected: | 89 protected: |
| 79 REQUIRE(0 == (N & (N-1))); | 90 REQUIRE(0 == (N & (N-1))); |
| 80 | 91 |
| 81 SkNi<N/2, T> fLo, fHi; | 92 SkNi<N/2, T> fLo, fHi; |
| 82 }; | 93 }; |
| 83 | 94 |
| 84 template <int N, typename T> | 95 template <int N, typename T> |
| 85 class SkNf { | 96 class SkNf { |
| 97 typedef SkNb<N, sizeof(T)> Nb; |
| 98 |
| 86 static int32_t MyNi(float); | 99 static int32_t MyNi(float); |
| 87 static int64_t MyNi(double); | 100 static int64_t MyNi(double); |
| 88 typedef decltype(MyNi(T())) I; | 101 typedef SkNi<N, decltype(MyNi(T()))> Ni; |
| 89 public: | 102 public: |
| 90 SkNf() {} | 103 SkNf() {} |
| 91 explicit SkNf(T val) : fLo(val), fHi(val) {} | 104 explicit SkNf(T val) : fLo(val), fHi(val) {} |
| 92 static SkNf Load(const T vals[N]) { | 105 static SkNf Load(const T vals[N]) { |
| 93 return SkNf(SkNf<N/2,T>::Load(vals), SkNf<N/2,T>::Load(vals+N/2)); | 106 return SkNf(SkNf<N/2,T>::Load(vals), SkNf<N/2,T>::Load(vals+N/2)); |
| 94 } | 107 } |
| 95 | 108 |
| 96 SkNf(T a, T b) : fLo(a), fHi(b) {
REQUIRE(N==2); } | 109 SkNf(T a, T b) : fLo(a), fHi(b) {
REQUIRE(N==2); } |
| 97 SkNf(T a, T b, T c, T d) : fLo(a,b), fHi(c,d) {
REQUIRE(N==4); } | 110 SkNf(T a, T b, T c, T d) : fLo(a,b), fHi(c,d) {
REQUIRE(N==4); } |
| 98 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); } | 111 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); } |
| 99 | 112 |
| 100 void store(T vals[N]) const { | 113 void store(T vals[N]) const { |
| 101 fLo.store(vals); | 114 fLo.store(vals); |
| 102 fHi.store(vals+N/2); | 115 fHi.store(vals+N/2); |
| 103 } | 116 } |
| 104 | 117 |
| 105 SkNi<N,I> castTrunc() const { return SkNi<N,I>(fLo.castTrunc(), fHi.castTrun
c()); } | 118 Ni castTrunc() const { return Ni(fLo.castTrunc(), fHi.castTrunc()); } |
| 106 | 119 |
| 107 SkNf operator + (const SkNf& o) const { return SkNf(fLo + o.fLo, fHi + o.fHi
); } | 120 SkNf operator + (const SkNf& o) const { return SkNf(fLo + o.fLo, fHi + o.fHi
); } |
| 108 SkNf operator - (const SkNf& o) const { return SkNf(fLo - o.fLo, fHi - o.fHi
); } | 121 SkNf operator - (const SkNf& o) const { return SkNf(fLo - o.fLo, fHi - o.fHi
); } |
| 109 SkNf operator * (const SkNf& o) const { return SkNf(fLo * o.fLo, fHi * o.fHi
); } | 122 SkNf operator * (const SkNf& o) const { return SkNf(fLo * o.fLo, fHi * o.fHi
); } |
| 110 SkNf operator / (const SkNf& o) const { return SkNf(fLo / o.fLo, fHi / o.fHi
); } | 123 SkNf operator / (const SkNf& o) const { return SkNf(fLo / o.fLo, fHi / o.fHi
); } |
| 111 | 124 |
| 112 SkNf operator == (const SkNf& o) const { return SkNf(fLo == o.fLo, fHi == o.
fHi); } | 125 Nb operator == (const SkNf& o) const { return Nb(fLo == o.fLo, fHi == o.fHi)
; } |
| 113 SkNf operator != (const SkNf& o) const { return SkNf(fLo != o.fLo, fHi != o.
fHi); } | 126 Nb operator != (const SkNf& o) const { return Nb(fLo != o.fLo, fHi != o.fHi)
; } |
| 114 SkNf operator < (const SkNf& o) const { return SkNf(fLo < o.fLo, fHi < o.
fHi); } | 127 Nb operator < (const SkNf& o) const { return Nb(fLo < o.fLo, fHi < o.fHi)
; } |
| 115 SkNf operator > (const SkNf& o) const { return SkNf(fLo > o.fLo, fHi > o.
fHi); } | 128 Nb operator > (const SkNf& o) const { return Nb(fLo > o.fLo, fHi > o.fHi)
; } |
| 116 SkNf operator <= (const SkNf& o) const { return SkNf(fLo <= o.fLo, fHi <= o.
fHi); } | 129 Nb operator <= (const SkNf& o) const { return Nb(fLo <= o.fLo, fHi <= o.fHi)
; } |
| 117 SkNf operator >= (const SkNf& o) const { return SkNf(fLo >= o.fLo, fHi >= o.
fHi); } | 130 Nb operator >= (const SkNf& o) const { return Nb(fLo >= o.fLo, fHi >= o.fHi)
; } |
| 118 | 131 |
| 119 static SkNf Min(const SkNf& l, const SkNf& r) { | 132 static SkNf Min(const SkNf& l, const SkNf& r) { |
| 120 return SkNf(SkNf<N/2,T>::Min(l.fLo, r.fLo), SkNf<N/2,T>::Min(l.fHi, r.fH
i)); | 133 return SkNf(SkNf<N/2,T>::Min(l.fLo, r.fLo), SkNf<N/2,T>::Min(l.fHi, r.fH
i)); |
| 121 } | 134 } |
| 122 static SkNf Max(const SkNf& l, const SkNf& r) { | 135 static SkNf Max(const SkNf& l, const SkNf& r) { |
| 123 return SkNf(SkNf<N/2,T>::Max(l.fLo, r.fLo), SkNf<N/2,T>::Max(l.fHi, r.fH
i)); | 136 return SkNf(SkNf<N/2,T>::Max(l.fLo, r.fLo), SkNf<N/2,T>::Max(l.fHi, r.fH
i)); |
| 124 } | 137 } |
| 125 | 138 |
| 126 SkNf sqrt() const { return SkNf(fLo. sqrt(), fHi. sqrt()); } | 139 SkNf sqrt() const { return SkNf(fLo. sqrt(), fHi. sqrt()); } |
| 127 | 140 |
| 128 // Generally, increasing precision, increasing cost. | 141 // Generally, increasing precision, increasing cost. |
| 129 SkNf rsqrt0() const { return SkNf(fLo.rsqrt0(), fHi.rsqrt0()); } | 142 SkNf rsqrt0() const { return SkNf(fLo.rsqrt0(), fHi.rsqrt0()); } |
| 130 SkNf rsqrt1() const { return SkNf(fLo.rsqrt1(), fHi.rsqrt1()); } | 143 SkNf rsqrt1() const { return SkNf(fLo.rsqrt1(), fHi.rsqrt1()); } |
| 131 SkNf rsqrt2() const { return SkNf(fLo.rsqrt2(), fHi.rsqrt2()); } | 144 SkNf rsqrt2() const { return SkNf(fLo.rsqrt2(), fHi.rsqrt2()); } |
| 132 | 145 |
| 133 SkNf invert() const { return SkNf(fLo. invert(), fHi. invert
()); } | 146 SkNf invert() const { return SkNf(fLo. invert(), fHi. invert
()); } |
| 134 SkNf approxInvert() const { return SkNf(fLo.approxInvert(), fHi.approxInvert
()); } | 147 SkNf approxInvert() const { return SkNf(fLo.approxInvert(), fHi.approxInvert
()); } |
| 135 | 148 |
| 136 template <int k> T kth() const { | 149 template <int k> T kth() const { |
| 137 SkASSERT(0 <= k && k < N); | 150 SkASSERT(0 <= k && k < N); |
| 138 return k < N/2 ? fLo.template kth<k>() : fHi.template kth<k-N/2>(); | 151 return k < N/2 ? fLo.template kth<k>() : fHi.template kth<k-N/2>(); |
| 139 } | 152 } |
| 140 | 153 |
| 141 bool allTrue() const { return fLo.allTrue() && fHi.allTrue(); } | |
| 142 bool anyTrue() const { return fLo.anyTrue() || fHi.anyTrue(); } | |
| 143 SkNf thenElse(const SkNf& t, const SkNf& e) const { | |
| 144 return SkNf(fLo.thenElse(t.fLo, t.fHi), fHi.thenElse(t.fLo, t.fHi)); | |
| 145 } | |
| 146 | |
| 147 protected: | 154 protected: |
| 148 REQUIRE(0 == (N & (N-1))); | 155 REQUIRE(0 == (N & (N-1))); |
| 149 SkNf(const SkNf<N/2, T>& lo, const SkNf<N/2, T>& hi) : fLo(lo), fHi(hi) {} | 156 SkNf(const SkNf<N/2, T>& lo, const SkNf<N/2, T>& hi) : fLo(lo), fHi(hi) {} |
| 150 | 157 |
| 151 SkNf<N/2, T> fLo, fHi; | 158 SkNf<N/2, T> fLo, fHi; |
| 152 }; | 159 }; |
| 153 | 160 |
| 154 | 161 |
| 155 // Bottom out the default implementations with scalars when nothing's been speci
alized. | 162 // Bottom out the default implementations with scalars when nothing's been speci
alized. |
| 156 | 163 |
| 164 template <int Bytes> |
| 165 class SkNb<1, Bytes> { |
| 166 public: |
| 167 SkNb() {} |
| 168 explicit SkNb(bool val) : fVal(val) {} |
| 169 bool allTrue() const { return fVal; } |
| 170 bool anyTrue() const { return fVal; } |
| 171 protected: |
| 172 bool fVal; |
| 173 }; |
| 174 |
| 157 template <typename T> | 175 template <typename T> |
| 158 class SkNi<1,T> { | 176 class SkNi<1,T> { |
| 159 public: | 177 public: |
| 160 SkNi() {} | 178 SkNi() {} |
| 161 explicit SkNi(T val) : fVal(val) {} | 179 explicit SkNi(T val) : fVal(val) {} |
| 162 static SkNi Load(const T vals[1]) { return SkNi(vals[0]); } | 180 static SkNi Load(const T vals[1]) { return SkNi(vals[0]); } |
| 163 | 181 |
| 164 void store(T vals[1]) const { vals[0] = fVal; } | 182 void store(T vals[1]) const { vals[0] = fVal; } |
| 165 | 183 |
| 166 SkNi saturatedAdd(const SkNi& o) const { | 184 SkNi saturatedAdd(const SkNi& o) const { |
| 167 SkASSERT((T)(~0) > 0); // TODO: support signed T | 185 SkASSERT((T)(~0) > 0); // TODO: support signed T |
| 168 T sum = fVal + o.fVal; | 186 T sum = fVal + o.fVal; |
| 169 return SkNi(sum < fVal ? (T)(~0) : sum); | 187 return SkNi(sum < fVal ? (T)(~0) : sum); |
| 170 } | 188 } |
| 171 | 189 |
| 172 SkNi operator + (const SkNi& o) const { return SkNi(fVal + o.fVal); } | 190 SkNi operator + (const SkNi& o) const { return SkNi(fVal + o.fVal); } |
| 173 SkNi operator - (const SkNi& o) const { return SkNi(fVal - o.fVal); } | 191 SkNi operator - (const SkNi& o) const { return SkNi(fVal - o.fVal); } |
| 174 SkNi operator * (const SkNi& o) const { return SkNi(fVal * o.fVal); } | 192 SkNi operator * (const SkNi& o) const { return SkNi(fVal * o.fVal); } |
| 175 | 193 |
| 176 SkNi operator << (int bits) const { return SkNi(fVal << bits); } | 194 SkNi operator << (int bits) const { return SkNi(fVal << bits); } |
| 177 SkNi operator >> (int bits) const { return SkNi(fVal >> bits); } | 195 SkNi operator >> (int bits) const { return SkNi(fVal >> bits); } |
| 178 | 196 |
| 179 static SkNi Min(const SkNi& a, const SkNi& b) { return SkNi(SkTMin(a.fVal, b
.fVal)); } | 197 static SkNi Min(const SkNi& a, const SkNi& b) { return SkNi(SkTMin(a.fVal, b
.fVal)); } |
| 180 SkNi operator <(const SkNi& o) const { return SkNi(fVal < o.fVal); } | |
| 181 | 198 |
| 182 template <int k> T kth() const { | 199 template <int k> T kth() const { |
| 183 SkASSERT(0 == k); | 200 SkASSERT(0 == k); |
| 184 return fVal; | 201 return fVal; |
| 185 } | 202 } |
| 186 | 203 |
| 187 bool allTrue() const { return fVal; } | |
| 188 bool anyTrue() const { return fVal; } | |
| 189 SkNi thenElse(const SkNi& t, const SkNi& e) const { return fVal ? t : e; } | |
| 190 | |
| 191 protected: | 204 protected: |
| 192 T fVal; | 205 T fVal; |
| 193 }; | 206 }; |
| 194 | 207 |
| 195 template <typename T> | 208 template <typename T> |
| 196 class SkNf<1,T> { | 209 class SkNf<1,T> { |
| 210 typedef SkNb<1, sizeof(T)> Nb; |
| 211 |
| 197 static int32_t MyNi(float); | 212 static int32_t MyNi(float); |
| 198 static int64_t MyNi(double); | 213 static int64_t MyNi(double); |
| 199 typedef decltype(MyNi(T())) I; | 214 typedef SkNi<1, decltype(MyNi(T()))> Ni; |
| 200 public: | 215 public: |
| 201 SkNf() {} | 216 SkNf() {} |
| 202 explicit SkNf(T val) : fVal(val) {} | 217 explicit SkNf(T val) : fVal(val) {} |
| 203 static SkNf Load(const T vals[1]) { return SkNf(vals[0]); } | 218 static SkNf Load(const T vals[1]) { return SkNf(vals[0]); } |
| 204 | 219 |
| 205 void store(T vals[1]) const { vals[0] = fVal; } | 220 void store(T vals[1]) const { vals[0] = fVal; } |
| 206 | 221 |
| 207 SkNi<1,I> castTrunc() const { return SkNi<1,I>(fVal); } | 222 Ni castTrunc() const { return Ni(fVal); } |
| 208 | 223 |
| 209 SkNf operator + (const SkNf& o) const { return SkNf(fVal + o.fVal); } | 224 SkNf operator + (const SkNf& o) const { return SkNf(fVal + o.fVal); } |
| 210 SkNf operator - (const SkNf& o) const { return SkNf(fVal - o.fVal); } | 225 SkNf operator - (const SkNf& o) const { return SkNf(fVal - o.fVal); } |
| 211 SkNf operator * (const SkNf& o) const { return SkNf(fVal * o.fVal); } | 226 SkNf operator * (const SkNf& o) const { return SkNf(fVal * o.fVal); } |
| 212 SkNf operator / (const SkNf& o) const { return SkNf(fVal / o.fVal); } | 227 SkNf operator / (const SkNf& o) const { return SkNf(fVal / o.fVal); } |
| 213 | 228 |
| 214 SkNf operator == (const SkNf& o) const { return SkNf(fVal == o.fVal); } | 229 Nb operator == (const SkNf& o) const { return Nb(fVal == o.fVal); } |
| 215 SkNf operator != (const SkNf& o) const { return SkNf(fVal != o.fVal); } | 230 Nb operator != (const SkNf& o) const { return Nb(fVal != o.fVal); } |
| 216 SkNf operator < (const SkNf& o) const { return SkNf(fVal < o.fVal); } | 231 Nb operator < (const SkNf& o) const { return Nb(fVal < o.fVal); } |
| 217 SkNf operator > (const SkNf& o) const { return SkNf(fVal > o.fVal); } | 232 Nb operator > (const SkNf& o) const { return Nb(fVal > o.fVal); } |
| 218 SkNf operator <= (const SkNf& o) const { return SkNf(fVal <= o.fVal); } | 233 Nb operator <= (const SkNf& o) const { return Nb(fVal <= o.fVal); } |
| 219 SkNf operator >= (const SkNf& o) const { return SkNf(fVal >= o.fVal); } | 234 Nb operator >= (const SkNf& o) const { return Nb(fVal >= o.fVal); } |
| 220 | 235 |
| 221 static SkNf Min(const SkNf& l, const SkNf& r) { return SkNf(SkTMin(l.fVal, r
.fVal)); } | 236 static SkNf Min(const SkNf& l, const SkNf& r) { return SkNf(SkTMin(l.fVal, r
.fVal)); } |
| 222 static SkNf Max(const SkNf& l, const SkNf& r) { return SkNf(SkTMax(l.fVal, r
.fVal)); } | 237 static SkNf Max(const SkNf& l, const SkNf& r) { return SkNf(SkTMax(l.fVal, r
.fVal)); } |
| 223 | 238 |
| 224 SkNf sqrt() const { return SkNf(Sqrt(fVal)); } | 239 SkNf sqrt() const { return SkNf(Sqrt(fVal)); } |
| 225 SkNf rsqrt0() const { return SkNf((T)1 / Sqrt(fVal)); } | 240 SkNf rsqrt0() const { return SkNf((T)1 / Sqrt(fVal)); } |
| 226 SkNf rsqrt1() const { return this->rsqrt0(); } | 241 SkNf rsqrt1() const { return this->rsqrt0(); } |
| 227 SkNf rsqrt2() const { return this->rsqrt1(); } | 242 SkNf rsqrt2() const { return this->rsqrt1(); } |
| 228 | 243 |
| 229 SkNf invert() const { return SkNf((T)1 / fVal); } | 244 SkNf invert() const { return SkNf((T)1 / fVal); } |
| 230 SkNf approxInvert() const { return this->invert(); } | 245 SkNf approxInvert() const { return this->invert(); } |
| 231 | 246 |
| 232 template <int k> T kth() const { | 247 template <int k> T kth() const { |
| 233 SkASSERT(k == 0); | 248 SkASSERT(k == 0); |
| 234 return fVal; | 249 return fVal; |
| 235 } | 250 } |
| 236 | 251 |
| 237 bool allTrue() const { return this->pun(); } | |
| 238 bool anyTrue() const { return this->pun(); } | |
| 239 SkNf thenElse(const SkNf& t, const SkNf& e) const { return this->pun() ? t :
e; } | |
| 240 | |
| 241 protected: | 252 protected: |
| 242 // We do double sqrts natively, or via floats for any other type. | 253 // We do double sqrts natively, or via floats for any other type. |
| 243 template <typename U> | 254 template <typename U> |
| 244 static U Sqrt(U val) { return (U) ::sqrtf((float)val); } | 255 static U Sqrt(U val) { return (U) ::sqrtf((float)val); } |
| 245 static double Sqrt(double val) { return ::sqrt ( val); } | 256 static double Sqrt(double val) { return ::sqrt ( val); } |
| 246 | 257 |
| 247 I pun() const { | |
| 248 union { T f; I i; } pun = { fVal }; | |
| 249 return pun.i; | |
| 250 } | |
| 251 | |
| 252 T fVal; | 258 T fVal; |
| 253 }; | 259 }; |
| 254 | 260 |
| 255 } // namespace | 261 } // namespace |
| 256 | 262 |
| 257 // Include platform specific specializations if available. | 263 // Include platform specific specializations if available. |
| 258 #ifndef SKNX_NO_SIMD | 264 #ifndef SKNX_NO_SIMD |
| 259 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 | 265 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 |
| 260 #include "../opts/SkNx_sse.h" | 266 #include "../opts/SkNx_sse.h" |
| 261 #elif defined(SK_ARM_HAS_NEON) | 267 #elif defined(SK_ARM_HAS_NEON) |
| (...skipping 14 matching lines...) Expand all Loading... |
| 276 typedef SkNi<4, uint16_t> Sk4h; | 282 typedef SkNi<4, uint16_t> Sk4h; |
| 277 typedef SkNi<8, uint16_t> Sk8h; | 283 typedef SkNi<8, uint16_t> Sk8h; |
| 278 typedef SkNi<16, uint16_t> Sk16h; | 284 typedef SkNi<16, uint16_t> Sk16h; |
| 279 | 285 |
| 280 typedef SkNi<16, uint8_t> Sk16b; | 286 typedef SkNi<16, uint8_t> Sk16b; |
| 281 | 287 |
| 282 typedef SkNi<4, int32_t> Sk4i; | 288 typedef SkNi<4, int32_t> Sk4i; |
| 283 typedef SkNi<4, uint32_t> Sk4u; | 289 typedef SkNi<4, uint32_t> Sk4u; |
| 284 | 290 |
| 285 #endif//SkNx_DEFINED | 291 #endif//SkNx_DEFINED |
| OLD | NEW |