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 | |
45 template <int N, typename T> | 29 template <int N, typename T> |
46 class SkNi { | 30 class SkNi { |
47 public: | 31 public: |
48 SkNi() {} | 32 SkNi() {} |
49 SkNi(const SkNi<N/2, T>& lo, const SkNi<N/2, T>& hi) : fLo(lo), fHi(hi) {} | 33 SkNi(const SkNi<N/2, T>& lo, const SkNi<N/2, T>& hi) : fLo(lo), fHi(hi) {} |
50 explicit SkNi(T val) : fLo(val), fHi(val) {} | 34 explicit SkNi(T val) : fLo(val), fHi(val) {} |
51 static SkNi Load(const T vals[N]) { | 35 static SkNi Load(const T vals[N]) { |
52 return SkNi(SkNi<N/2,T>::Load(vals), SkNi<N/2,T>::Load(vals+N/2)); | 36 return SkNi(SkNi<N/2,T>::Load(vals), SkNi<N/2,T>::Load(vals+N/2)); |
53 } | 37 } |
54 | 38 |
(...skipping 16 matching lines...) Expand all Loading... |
71 SkNi operator + (const SkNi& o) const { return SkNi(fLo + o.fLo, fHi + o.fHi
); } | 55 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
); } | 56 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
); } | 57 SkNi operator * (const SkNi& o) const { return SkNi(fLo * o.fLo, fHi * o.fHi
); } |
74 | 58 |
75 SkNi operator << (int bits) const { return SkNi(fLo << bits, fHi << bits); } | 59 SkNi operator << (int bits) const { return SkNi(fLo << bits, fHi << bits); } |
76 SkNi operator >> (int bits) const { return SkNi(fLo >> bits, fHi >> bits); } | 60 SkNi operator >> (int bits) const { return SkNi(fLo >> bits, fHi >> bits); } |
77 | 61 |
78 static SkNi Min(const SkNi& a, const SkNi& b) { | 62 static SkNi Min(const SkNi& a, const SkNi& b) { |
79 return SkNi(SkNi<N/2, T>::Min(a.fLo, b.fLo), SkNi<N/2, T>::Min(a.fHi, b.
fHi)); | 63 return SkNi(SkNi<N/2, T>::Min(a.fLo, b.fLo), SkNi<N/2, T>::Min(a.fHi, b.
fHi)); |
80 } | 64 } |
81 | 65 SkNi operator < (const SkNi& o) const { return SkNi(fLo < o.fLo, fHi < o.fHi
); } |
82 // TODO: comparisons, max? | |
83 | 66 |
84 template <int k> T kth() const { | 67 template <int k> T kth() const { |
85 SkASSERT(0 <= k && k < N); | 68 SkASSERT(0 <= k && k < N); |
86 return k < N/2 ? fLo.template kth<k>() : fHi.template kth<k-N/2>(); | 69 return k < N/2 ? fLo.template kth<k>() : fHi.template kth<k-N/2>(); |
87 } | 70 } |
88 | 71 |
| 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 |
89 protected: | 78 protected: |
90 REQUIRE(0 == (N & (N-1))); | 79 REQUIRE(0 == (N & (N-1))); |
91 | 80 |
92 SkNi<N/2, T> fLo, fHi; | 81 SkNi<N/2, T> fLo, fHi; |
93 }; | 82 }; |
94 | 83 |
95 template <int N, typename T> | 84 template <int N, typename T> |
96 class SkNf { | 85 class SkNf { |
97 typedef SkNb<N, sizeof(T)> Nb; | |
98 | |
99 static int32_t MyNi(float); | 86 static int32_t MyNi(float); |
100 static int64_t MyNi(double); | 87 static int64_t MyNi(double); |
101 typedef SkNi<N, decltype(MyNi(T()))> Ni; | 88 typedef decltype(MyNi(T())) I; |
102 public: | 89 public: |
103 SkNf() {} | 90 SkNf() {} |
104 explicit SkNf(T val) : fLo(val), fHi(val) {} | 91 explicit SkNf(T val) : fLo(val), fHi(val) {} |
105 static SkNf Load(const T vals[N]) { | 92 static SkNf Load(const T vals[N]) { |
106 return SkNf(SkNf<N/2,T>::Load(vals), SkNf<N/2,T>::Load(vals+N/2)); | 93 return SkNf(SkNf<N/2,T>::Load(vals), SkNf<N/2,T>::Load(vals+N/2)); |
107 } | 94 } |
108 | 95 |
109 SkNf(T a, T b) : fLo(a), fHi(b) {
REQUIRE(N==2); } | 96 SkNf(T a, T b) : fLo(a), fHi(b) {
REQUIRE(N==2); } |
110 SkNf(T a, T b, T c, T d) : fLo(a,b), fHi(c,d) {
REQUIRE(N==4); } | 97 SkNf(T a, T b, T c, T d) : fLo(a,b), fHi(c,d) {
REQUIRE(N==4); } |
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); } | 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); } |
112 | 99 |
113 void store(T vals[N]) const { | 100 void store(T vals[N]) const { |
114 fLo.store(vals); | 101 fLo.store(vals); |
115 fHi.store(vals+N/2); | 102 fHi.store(vals+N/2); |
116 } | 103 } |
117 | 104 |
118 Ni castTrunc() const { return Ni(fLo.castTrunc(), fHi.castTrunc()); } | 105 SkNi<N,I> castTrunc() const { return SkNi<N,I>(fLo.castTrunc(), fHi.castTrun
c()); } |
119 | 106 |
120 SkNf operator + (const SkNf& o) const { return SkNf(fLo + o.fLo, fHi + o.fHi
); } | 107 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
); } | 108 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
); } | 109 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
); } | 110 SkNf operator / (const SkNf& o) const { return SkNf(fLo / o.fLo, fHi / o.fHi
); } |
124 | 111 |
125 Nb operator == (const SkNf& o) const { return Nb(fLo == o.fLo, fHi == o.fHi)
; } | 112 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)
; } | 113 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)
; } | 114 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)
; } | 115 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)
; } | 116 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)
; } | 117 SkNf operator >= (const SkNf& o) const { return SkNf(fLo >= o.fLo, fHi >= o.
fHi); } |
131 | 118 |
132 static SkNf Min(const SkNf& l, const SkNf& r) { | 119 static SkNf Min(const SkNf& l, const SkNf& r) { |
133 return SkNf(SkNf<N/2,T>::Min(l.fLo, r.fLo), SkNf<N/2,T>::Min(l.fHi, r.fH
i)); | 120 return SkNf(SkNf<N/2,T>::Min(l.fLo, r.fLo), SkNf<N/2,T>::Min(l.fHi, r.fH
i)); |
134 } | 121 } |
135 static SkNf Max(const SkNf& l, const SkNf& r) { | 122 static SkNf Max(const SkNf& l, const SkNf& r) { |
136 return SkNf(SkNf<N/2,T>::Max(l.fLo, r.fLo), SkNf<N/2,T>::Max(l.fHi, r.fH
i)); | 123 return SkNf(SkNf<N/2,T>::Max(l.fLo, r.fLo), SkNf<N/2,T>::Max(l.fHi, r.fH
i)); |
137 } | 124 } |
138 | 125 |
139 SkNf sqrt() const { return SkNf(fLo. sqrt(), fHi. sqrt()); } | 126 SkNf sqrt() const { return SkNf(fLo. sqrt(), fHi. sqrt()); } |
140 | 127 |
141 // Generally, increasing precision, increasing cost. | 128 // Generally, increasing precision, increasing cost. |
142 SkNf rsqrt0() const { return SkNf(fLo.rsqrt0(), fHi.rsqrt0()); } | 129 SkNf rsqrt0() const { return SkNf(fLo.rsqrt0(), fHi.rsqrt0()); } |
143 SkNf rsqrt1() const { return SkNf(fLo.rsqrt1(), fHi.rsqrt1()); } | 130 SkNf rsqrt1() const { return SkNf(fLo.rsqrt1(), fHi.rsqrt1()); } |
144 SkNf rsqrt2() const { return SkNf(fLo.rsqrt2(), fHi.rsqrt2()); } | 131 SkNf rsqrt2() const { return SkNf(fLo.rsqrt2(), fHi.rsqrt2()); } |
145 | 132 |
146 SkNf invert() const { return SkNf(fLo. invert(), fHi. invert
()); } | 133 SkNf invert() const { return SkNf(fLo. invert(), fHi. invert
()); } |
147 SkNf approxInvert() const { return SkNf(fLo.approxInvert(), fHi.approxInvert
()); } | 134 SkNf approxInvert() const { return SkNf(fLo.approxInvert(), fHi.approxInvert
()); } |
148 | 135 |
149 template <int k> T kth() const { | 136 template <int k> T kth() const { |
150 SkASSERT(0 <= k && k < N); | 137 SkASSERT(0 <= k && k < N); |
151 return k < N/2 ? fLo.template kth<k>() : fHi.template kth<k-N/2>(); | 138 return k < N/2 ? fLo.template kth<k>() : fHi.template kth<k-N/2>(); |
152 } | 139 } |
153 | 140 |
| 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 |
154 protected: | 147 protected: |
155 REQUIRE(0 == (N & (N-1))); | 148 REQUIRE(0 == (N & (N-1))); |
156 SkNf(const SkNf<N/2, T>& lo, const SkNf<N/2, T>& hi) : fLo(lo), fHi(hi) {} | 149 SkNf(const SkNf<N/2, T>& lo, const SkNf<N/2, T>& hi) : fLo(lo), fHi(hi) {} |
157 | 150 |
158 SkNf<N/2, T> fLo, fHi; | 151 SkNf<N/2, T> fLo, fHi; |
159 }; | 152 }; |
160 | 153 |
161 | 154 |
162 // Bottom out the default implementations with scalars when nothing's been speci
alized. | 155 // Bottom out the default implementations with scalars when nothing's been speci
alized. |
163 | 156 |
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 | |
175 template <typename T> | 157 template <typename T> |
176 class SkNi<1,T> { | 158 class SkNi<1,T> { |
177 public: | 159 public: |
178 SkNi() {} | 160 SkNi() {} |
179 explicit SkNi(T val) : fVal(val) {} | 161 explicit SkNi(T val) : fVal(val) {} |
180 static SkNi Load(const T vals[1]) { return SkNi(vals[0]); } | 162 static SkNi Load(const T vals[1]) { return SkNi(vals[0]); } |
181 | 163 |
182 void store(T vals[1]) const { vals[0] = fVal; } | 164 void store(T vals[1]) const { vals[0] = fVal; } |
183 | 165 |
184 SkNi saturatedAdd(const SkNi& o) const { | 166 SkNi saturatedAdd(const SkNi& o) const { |
185 SkASSERT((T)(~0) > 0); // TODO: support signed T | 167 SkASSERT((T)(~0) > 0); // TODO: support signed T |
186 T sum = fVal + o.fVal; | 168 T sum = fVal + o.fVal; |
187 return SkNi(sum < fVal ? (T)(~0) : sum); | 169 return SkNi(sum < fVal ? (T)(~0) : sum); |
188 } | 170 } |
189 | 171 |
190 SkNi operator + (const SkNi& o) const { return SkNi(fVal + o.fVal); } | 172 SkNi operator + (const SkNi& o) const { return SkNi(fVal + o.fVal); } |
191 SkNi operator - (const SkNi& o) const { return SkNi(fVal - o.fVal); } | 173 SkNi operator - (const SkNi& o) const { return SkNi(fVal - o.fVal); } |
192 SkNi operator * (const SkNi& o) const { return SkNi(fVal * o.fVal); } | 174 SkNi operator * (const SkNi& o) const { return SkNi(fVal * o.fVal); } |
193 | 175 |
194 SkNi operator << (int bits) const { return SkNi(fVal << bits); } | 176 SkNi operator << (int bits) const { return SkNi(fVal << bits); } |
195 SkNi operator >> (int bits) const { return SkNi(fVal >> bits); } | 177 SkNi operator >> (int bits) const { return SkNi(fVal >> bits); } |
196 | 178 |
197 static SkNi Min(const SkNi& a, const SkNi& b) { return SkNi(SkTMin(a.fVal, b
.fVal)); } | 179 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); } |
198 | 181 |
199 template <int k> T kth() const { | 182 template <int k> T kth() const { |
200 SkASSERT(0 == k); | 183 SkASSERT(0 == k); |
201 return fVal; | 184 return fVal; |
202 } | 185 } |
203 | 186 |
| 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 |
204 protected: | 191 protected: |
205 T fVal; | 192 T fVal; |
206 }; | 193 }; |
207 | 194 |
208 template <typename T> | 195 template <typename T> |
209 class SkNf<1,T> { | 196 class SkNf<1,T> { |
210 typedef SkNb<1, sizeof(T)> Nb; | |
211 | |
212 static int32_t MyNi(float); | 197 static int32_t MyNi(float); |
213 static int64_t MyNi(double); | 198 static int64_t MyNi(double); |
214 typedef SkNi<1, decltype(MyNi(T()))> Ni; | 199 typedef decltype(MyNi(T())) I; |
215 public: | 200 public: |
216 SkNf() {} | 201 SkNf() {} |
217 explicit SkNf(T val) : fVal(val) {} | 202 explicit SkNf(T val) : fVal(val) {} |
218 static SkNf Load(const T vals[1]) { return SkNf(vals[0]); } | 203 static SkNf Load(const T vals[1]) { return SkNf(vals[0]); } |
219 | 204 |
220 void store(T vals[1]) const { vals[0] = fVal; } | 205 void store(T vals[1]) const { vals[0] = fVal; } |
221 | 206 |
222 Ni castTrunc() const { return Ni(fVal); } | 207 SkNi<1,I> castTrunc() const { return SkNi<1,I>(fVal); } |
223 | 208 |
224 SkNf operator + (const SkNf& o) const { return SkNf(fVal + o.fVal); } | 209 SkNf operator + (const SkNf& o) const { return SkNf(fVal + o.fVal); } |
225 SkNf operator - (const SkNf& o) const { return SkNf(fVal - o.fVal); } | 210 SkNf operator - (const SkNf& o) const { return SkNf(fVal - o.fVal); } |
226 SkNf operator * (const SkNf& o) const { return SkNf(fVal * o.fVal); } | 211 SkNf operator * (const SkNf& o) const { return SkNf(fVal * o.fVal); } |
227 SkNf operator / (const SkNf& o) const { return SkNf(fVal / o.fVal); } | 212 SkNf operator / (const SkNf& o) const { return SkNf(fVal / o.fVal); } |
228 | 213 |
229 Nb operator == (const SkNf& o) const { return Nb(fVal == o.fVal); } | 214 SkNf operator == (const SkNf& o) const { return SkNf(fVal == o.fVal); } |
230 Nb operator != (const SkNf& o) const { return Nb(fVal != o.fVal); } | 215 SkNf operator != (const SkNf& o) const { return SkNf(fVal != o.fVal); } |
231 Nb operator < (const SkNf& o) const { return Nb(fVal < o.fVal); } | 216 SkNf operator < (const SkNf& o) const { return SkNf(fVal < o.fVal); } |
232 Nb operator > (const SkNf& o) const { return Nb(fVal > o.fVal); } | 217 SkNf operator > (const SkNf& o) const { return SkNf(fVal > o.fVal); } |
233 Nb operator <= (const SkNf& o) const { return Nb(fVal <= o.fVal); } | 218 SkNf operator <= (const SkNf& o) const { return SkNf(fVal <= o.fVal); } |
234 Nb operator >= (const SkNf& o) const { return Nb(fVal >= o.fVal); } | 219 SkNf operator >= (const SkNf& o) const { return SkNf(fVal >= o.fVal); } |
235 | 220 |
236 static SkNf Min(const SkNf& l, const SkNf& r) { return SkNf(SkTMin(l.fVal, r
.fVal)); } | 221 static SkNf Min(const SkNf& l, const SkNf& r) { return SkNf(SkTMin(l.fVal, r
.fVal)); } |
237 static SkNf Max(const SkNf& l, const SkNf& r) { return SkNf(SkTMax(l.fVal, r
.fVal)); } | 222 static SkNf Max(const SkNf& l, const SkNf& r) { return SkNf(SkTMax(l.fVal, r
.fVal)); } |
238 | 223 |
239 SkNf sqrt() const { return SkNf(Sqrt(fVal)); } | 224 SkNf sqrt() const { return SkNf(Sqrt(fVal)); } |
240 SkNf rsqrt0() const { return SkNf((T)1 / Sqrt(fVal)); } | 225 SkNf rsqrt0() const { return SkNf((T)1 / Sqrt(fVal)); } |
241 SkNf rsqrt1() const { return this->rsqrt0(); } | 226 SkNf rsqrt1() const { return this->rsqrt0(); } |
242 SkNf rsqrt2() const { return this->rsqrt1(); } | 227 SkNf rsqrt2() const { return this->rsqrt1(); } |
243 | 228 |
244 SkNf invert() const { return SkNf((T)1 / fVal); } | 229 SkNf invert() const { return SkNf((T)1 / fVal); } |
245 SkNf approxInvert() const { return this->invert(); } | 230 SkNf approxInvert() const { return this->invert(); } |
246 | 231 |
247 template <int k> T kth() const { | 232 template <int k> T kth() const { |
248 SkASSERT(k == 0); | 233 SkASSERT(k == 0); |
249 return fVal; | 234 return fVal; |
250 } | 235 } |
251 | 236 |
| 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 |
252 protected: | 241 protected: |
253 // We do double sqrts natively, or via floats for any other type. | 242 // We do double sqrts natively, or via floats for any other type. |
254 template <typename U> | 243 template <typename U> |
255 static U Sqrt(U val) { return (U) ::sqrtf((float)val); } | 244 static U Sqrt(U val) { return (U) ::sqrtf((float)val); } |
256 static double Sqrt(double val) { return ::sqrt ( val); } | 245 static double Sqrt(double val) { return ::sqrt ( val); } |
257 | 246 |
| 247 I pun() const { |
| 248 union { T f; I i; } pun = { fVal }; |
| 249 return pun.i; |
| 250 } |
| 251 |
258 T fVal; | 252 T fVal; |
259 }; | 253 }; |
260 | 254 |
261 } // namespace | 255 } // namespace |
262 | 256 |
263 // Include platform specific specializations if available. | 257 // Include platform specific specializations if available. |
264 #ifndef SKNX_NO_SIMD | 258 #ifndef SKNX_NO_SIMD |
265 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 | 259 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 |
266 #include "../opts/SkNx_sse.h" | 260 #include "../opts/SkNx_sse.h" |
267 #elif defined(SK_ARM_HAS_NEON) | 261 #elif defined(SK_ARM_HAS_NEON) |
(...skipping 14 matching lines...) Expand all Loading... |
282 typedef SkNi<4, uint16_t> Sk4h; | 276 typedef SkNi<4, uint16_t> Sk4h; |
283 typedef SkNi<8, uint16_t> Sk8h; | 277 typedef SkNi<8, uint16_t> Sk8h; |
284 typedef SkNi<16, uint16_t> Sk16h; | 278 typedef SkNi<16, uint16_t> Sk16h; |
285 | 279 |
286 typedef SkNi<16, uint8_t> Sk16b; | 280 typedef SkNi<16, uint8_t> Sk16b; |
287 | 281 |
288 typedef SkNi<4, int32_t> Sk4i; | 282 typedef SkNi<4, int32_t> Sk4i; |
289 typedef SkNi<4, uint32_t> Sk4u; | 283 typedef SkNi<4, uint32_t> Sk4u; |
290 | 284 |
291 #endif//SkNx_DEFINED | 285 #endif//SkNx_DEFINED |
OLD | NEW |