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 |