Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(34)

Side by Side Diff: src/core/SkNx.h

Issue 1464623002: Add SkNx_cast(). (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: derp, is stands for _ints_ Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/opts/SkNx_avx.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 template <int N, typename T> 29 template <int N, typename T>
30 class SkNi { 30 class SkNx {
31 public: 31 public:
32 SkNi() {} 32 SkNx() {}
33 SkNi(const SkNi<N/2, T>& lo, const SkNi<N/2, T>& hi) : fLo(lo), fHi(hi) {} 33 SkNx(const SkNx<N/2, T>& lo, const SkNx<N/2, T>& hi) : fLo(lo), fHi(hi) {}
34 SkNi(T val) : fLo(val), fHi(val) {} 34 SkNx(T val) : fLo(val), fHi(val) {}
35 static SkNi Load(const T vals[N]) { 35 static SkNx Load(const T vals[N]) {
36 return SkNi(SkNi<N/2,T>::Load(vals), SkNi<N/2,T>::Load(vals+N/2)); 36 return SkNx(SkNx<N/2,T>::Load(vals), SkNx<N/2,T>::Load(vals+N/2));
37 } 37 }
38 38
39 SkNi(T a, T b) : fLo(a), fHi(b) { REQUIRE(N==2); } 39 SkNx(T a, T b) : fLo(a), fHi(b) { REQUIRE(N==2); }
40 SkNi(T a, T b, T c, T d) : fLo(a,b), fHi(c,d) { REQUIRE(N==4); } 40 SkNx(T a, T b, T c, T d) : fLo(a,b), fHi(c,d) { REQUIRE(N==4); }
41 SkNi(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); } 41 SkNx(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); }
42 SkNi(T a, T b, T c, T d, T e, T f, T g, T h, 42 SkNx(T a, T b, T c, T d, T e, T f, T g, T h,
43 T i, T j, T k, T l, T m, T n, T o, T p) 43 T i, T j, T k, T l, T m, T n, T o, T p)
44 : fLo(a,b,c,d, e,f,g,h), fHi(i,j,k,l, m,n,o,p) { REQUIRE(N==16); } 44 : fLo(a,b,c,d, e,f,g,h), fHi(i,j,k,l, m,n,o,p) { REQUIRE(N==16); }
45 45
46 void store(T vals[N]) const { 46 void store(T vals[N]) const {
47 fLo.store(vals); 47 fLo.store(vals);
48 fHi.store(vals+N/2); 48 fHi.store(vals+N/2);
49 } 49 }
50 50
51 SkNi saturatedAdd(const SkNi& o) const { 51 SkNx saturatedAdd(const SkNx& o) const {
52 return SkNi(fLo.saturatedAdd(o.fLo), fHi.saturatedAdd(o.fHi)); 52 return SkNx(fLo.saturatedAdd(o.fLo), fHi.saturatedAdd(o.fHi));
53 } 53 }
54 54
55 SkNi operator + (const SkNi& o) const { return SkNi(fLo + o.fLo, fHi + o.fHi ); } 55 SkNx operator + (const SkNx& o) const { return SkNx(fLo + o.fLo, fHi + o.fHi ); }
56 SkNi operator - (const SkNi& o) const { return SkNi(fLo - o.fLo, fHi - o.fHi ); } 56 SkNx operator - (const SkNx& o) const { return SkNx(fLo - o.fLo, fHi - o.fHi ); }
57 SkNi operator * (const SkNi& o) const { return SkNi(fLo * o.fLo, fHi * o.fHi ); } 57 SkNx operator * (const SkNx& o) const { return SkNx(fLo * o.fLo, fHi * o.fHi ); }
58 58
59 SkNi operator << (int bits) const { return SkNi(fLo << bits, fHi << bits); } 59 SkNx operator << (int bits) const { return SkNx(fLo << bits, fHi << bits); }
60 SkNi operator >> (int bits) const { return SkNi(fLo >> bits, fHi >> bits); } 60 SkNx operator >> (int bits) const { return SkNx(fLo >> bits, fHi >> bits); }
61 61
62 static SkNi Min(const SkNi& a, const SkNi& b) { 62 static SkNx Min(const SkNx& a, const SkNx& b) {
63 return SkNi(SkNi<N/2, T>::Min(a.fLo, b.fLo), SkNi<N/2, T>::Min(a.fHi, b. fHi)); 63 return SkNx(SkNx<N/2, T>::Min(a.fLo, b.fLo), SkNx<N/2, T>::Min(a.fHi, b. fHi));
64 } 64 }
65 SkNi operator < (const SkNi& o) const { return SkNi(fLo < o.fLo, fHi < o.fHi ); } 65 SkNx operator < (const SkNx& o) const { return SkNx(fLo < o.fLo, fHi < o.fHi ); }
66 66
67 template <int k> T kth() const { 67 template <int k> T kth() const {
68 SkASSERT(0 <= k && k < N); 68 SkASSERT(0 <= k && k < N);
69 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>();
70 } 70 }
71 71
72 bool allTrue() const { return fLo.allTrue() && fHi.allTrue(); } 72 bool allTrue() const { return fLo.allTrue() && fHi.allTrue(); }
73 bool anyTrue() const { return fLo.anyTrue() || fHi.anyTrue(); } 73 bool anyTrue() const { return fLo.anyTrue() || fHi.anyTrue(); }
74 SkNi thenElse(const SkNi& t, const SkNi& e) const { 74 SkNx thenElse(const SkNx& t, const SkNx& e) const {
75 return SkNi(fLo.thenElse(t.fLo, e.fLo), fHi.thenElse(t.fHi, e.fHi)); 75 return SkNx(fLo.thenElse(t.fLo, e.fLo), fHi.thenElse(t.fHi, e.fHi));
76 } 76 }
77 77
78 protected: 78 protected:
79 REQUIRE(0 == (N & (N-1))); 79 REQUIRE(0 == (N & (N-1)));
80 80
81 SkNi<N/2, T> fLo, fHi; 81 SkNx<N/2, T> fLo, fHi;
82 }; 82 };
83 83
84 template <int N> 84 template <int N>
85 class SkNf { 85 class SkNx<N,float> {
86 public: 86 public:
87 SkNf() {} 87 SkNx() {}
88 SkNf(float val) : fLo(val), fHi(val) {} 88 SkNx(float val) : fLo(val), fHi(val) {}
89 static SkNf Load(const float vals[N]) { 89 static SkNx Load(const float vals[N]) {
90 return SkNf(SkNf<N/2>::Load(vals), SkNf<N/2>::Load(vals+N/2)); 90 return SkNx(SkNx<N/2, float>::Load(vals), SkNx<N/2, float>::Load(vals+N/ 2));
91 } 91 }
92 // FromBytes() and toBytes() specializations may assume their argument is N- byte aligned. 92 // FromBytes() and toBytes() specializations may assume their argument is N- byte aligned.
93 // E.g. Sk4f::FromBytes() may assume it's reading from a 4-byte-aligned poin ter. 93 // E.g. Sk4f::FromBytes() may assume it's reading from a 4-byte-aligned poin ter.
94 // Converts [0,255] bytes to [0.0, 255.0] floats. 94 // Converts [0,255] bytes to [0.0, 255.0] floats.
95 static SkNf FromBytes(const uint8_t bytes[N]) { 95 static SkNx FromBytes(const uint8_t bytes[N]) {
96 return SkNf(SkNf<N/2>::FromBytes(bytes), SkNf<N/2>::FromBytes(bytes+N/2) ); 96 return SkNx(SkNx<N/2, float>::FromBytes(bytes), SkNx<N/2, float>::FromBy tes(bytes+N/2));
97 } 97 }
98 98
99 SkNf(float a, float b) : fLo(a), fHi(b) { REQUIRE(N==2 ); } 99 SkNx(float a, float b) : fLo(a), fHi(b) { REQUIRE(N==2 ); }
100 SkNf(float a, float b, float c, float d) : fLo(a,b), fHi(c,d) { REQUIRE(N==4 ); } 100 SkNx(float a, float b, float c, float d) : fLo(a,b), fHi(c,d) { REQUIRE(N==4 ); }
101 SkNf(float a, float b, float c, float d, float e, float f, float g, float h) 101 SkNx(float a, float b, float c, float d, float e, float f, float g, float h)
102 : fLo(a,b,c,d) 102 : fLo(a,b,c,d)
103 , fHi(e,f,g,h) { REQUIRE(N==8); } 103 , fHi(e,f,g,h) { REQUIRE(N==8); }
104 104
105 void store(float vals[N]) const { 105 void store(float vals[N]) const {
106 fLo.store(vals); 106 fLo.store(vals);
107 fHi.store(vals+N/2); 107 fHi.store(vals+N/2);
108 } 108 }
109 // Please see note on FromBytes(). 109 // Please see note on FromBytes().
110 // Clamps to [0.0,255.0] floats and truncates to [0,255] bytes. 110 // Clamps to [0.0,255.0] floats and truncates to [0,255] bytes.
111 void toBytes(uint8_t bytes[N]) const { 111 void toBytes(uint8_t bytes[N]) const {
112 fLo.toBytes(bytes); 112 fLo.toBytes(bytes);
113 fHi.toBytes(bytes+N/2); 113 fHi.toBytes(bytes+N/2);
114 } 114 }
115 115
116 SkNf operator + (const SkNf& o) const { return SkNf(fLo + o.fLo, fHi + o.fHi ); } 116 SkNx operator + (const SkNx& o) const { return SkNx(fLo + o.fLo, fHi + o.fHi ); }
117 SkNf operator - (const SkNf& o) const { return SkNf(fLo - o.fLo, fHi - o.fHi ); } 117 SkNx operator - (const SkNx& o) const { return SkNx(fLo - o.fLo, fHi - o.fHi ); }
118 SkNf operator * (const SkNf& o) const { return SkNf(fLo * o.fLo, fHi * o.fHi ); } 118 SkNx operator * (const SkNx& o) const { return SkNx(fLo * o.fLo, fHi * o.fHi ); }
119 SkNf operator / (const SkNf& o) const { return SkNf(fLo / o.fLo, fHi / o.fHi ); } 119 SkNx operator / (const SkNx& o) const { return SkNx(fLo / o.fLo, fHi / o.fHi ); }
120 120
121 SkNf operator == (const SkNf& o) const { return SkNf(fLo == o.fLo, fHi == o. fHi); } 121 SkNx operator == (const SkNx& o) const { return SkNx(fLo == o.fLo, fHi == o. fHi); }
122 SkNf operator != (const SkNf& o) const { return SkNf(fLo != o.fLo, fHi != o. fHi); } 122 SkNx operator != (const SkNx& o) const { return SkNx(fLo != o.fLo, fHi != o. fHi); }
123 SkNf operator < (const SkNf& o) const { return SkNf(fLo < o.fLo, fHi < o. fHi); } 123 SkNx operator < (const SkNx& o) const { return SkNx(fLo < o.fLo, fHi < o. fHi); }
124 SkNf operator > (const SkNf& o) const { return SkNf(fLo > o.fLo, fHi > o. fHi); } 124 SkNx operator > (const SkNx& o) const { return SkNx(fLo > o.fLo, fHi > o. fHi); }
125 SkNf operator <= (const SkNf& o) const { return SkNf(fLo <= o.fLo, fHi <= o. fHi); } 125 SkNx operator <= (const SkNx& o) const { return SkNx(fLo <= o.fLo, fHi <= o. fHi); }
126 SkNf operator >= (const SkNf& o) const { return SkNf(fLo >= o.fLo, fHi >= o. fHi); } 126 SkNx operator >= (const SkNx& o) const { return SkNx(fLo >= o.fLo, fHi >= o. fHi); }
127 127
128 static SkNf Min(const SkNf& l, const SkNf& r) { 128 static SkNx Min(const SkNx& l, const SkNx& r) {
129 return SkNf(SkNf<N/2>::Min(l.fLo, r.fLo), SkNf<N/2>::Min(l.fHi, r.fHi)); 129 return SkNx(SkNx<N/2, float>::Min(l.fLo, r.fLo), SkNx<N/2, float>::Min(l .fHi, r.fHi));
130 } 130 }
131 static SkNf Max(const SkNf& l, const SkNf& r) { 131 static SkNx Max(const SkNx& l, const SkNx& r) {
132 return SkNf(SkNf<N/2>::Max(l.fLo, r.fLo), SkNf<N/2>::Max(l.fHi, r.fHi)); 132 return SkNx(SkNx<N/2, float>::Max(l.fLo, r.fLo), SkNx<N/2, float>::Max(l .fHi, r.fHi));
133 } 133 }
134 134
135 SkNf sqrt() const { return SkNf(fLo. sqrt(), fHi. sqrt()); } 135 SkNx sqrt() const { return SkNx(fLo. sqrt(), fHi. sqrt()); }
136 136
137 // Generally, increasing precision, increasing cost. 137 // Generally, increasing precision, increasing cost.
138 SkNf rsqrt0() const { return SkNf(fLo.rsqrt0(), fHi.rsqrt0()); } 138 SkNx rsqrt0() const { return SkNx(fLo.rsqrt0(), fHi.rsqrt0()); }
139 SkNf rsqrt1() const { return SkNf(fLo.rsqrt1(), fHi.rsqrt1()); } 139 SkNx rsqrt1() const { return SkNx(fLo.rsqrt1(), fHi.rsqrt1()); }
140 SkNf rsqrt2() const { return SkNf(fLo.rsqrt2(), fHi.rsqrt2()); } 140 SkNx rsqrt2() const { return SkNx(fLo.rsqrt2(), fHi.rsqrt2()); }
141 141
142 SkNf invert() const { return SkNf(fLo. invert(), fHi. invert ()); } 142 SkNx invert() const { return SkNx(fLo. invert(), fHi. invert ()); }
143 SkNf approxInvert() const { return SkNf(fLo.approxInvert(), fHi.approxInvert ()); } 143 SkNx approxInvert() const { return SkNx(fLo.approxInvert(), fHi.approxInvert ()); }
144 144
145 template <int k> float kth() const { 145 template <int k> float kth() const {
146 SkASSERT(0 <= k && k < N); 146 SkASSERT(0 <= k && k < N);
147 return k < N/2 ? fLo.template kth<k>() : fHi.template kth<k-N/2>(); 147 return k < N/2 ? fLo.template kth<k>() : fHi.template kth<k-N/2>();
148 } 148 }
149 149
150 bool allTrue() const { return fLo.allTrue() && fHi.allTrue(); } 150 bool allTrue() const { return fLo.allTrue() && fHi.allTrue(); }
151 bool anyTrue() const { return fLo.anyTrue() || fHi.anyTrue(); } 151 bool anyTrue() const { return fLo.anyTrue() || fHi.anyTrue(); }
152 SkNf thenElse(const SkNf& t, const SkNf& e) const { 152 SkNx thenElse(const SkNx& t, const SkNx& e) const {
153 return SkNf(fLo.thenElse(t.fLo, e.fLo), fHi.thenElse(t.fHi, e.fHi)); 153 return SkNx(fLo.thenElse(t.fLo, e.fLo), fHi.thenElse(t.fHi, e.fHi));
154 } 154 }
155 155
156 protected: 156 protected:
157 REQUIRE(0 == (N & (N-1))); 157 REQUIRE(0 == (N & (N-1)));
158 SkNf(const SkNf<N/2>& lo, const SkNf<N/2>& hi) : fLo(lo), fHi(hi) {} 158 SkNx(const SkNx<N/2, float>& lo, const SkNx<N/2, float>& hi) : fLo(lo), fHi( hi) {}
159 159
160 SkNf<N/2> fLo, fHi; 160 SkNx<N/2, float> fLo, fHi;
161 }; 161 };
162 162
163 163
164 // Bottom out the default implementations with scalars when nothing's been speci alized. 164 // Bottom out the default implementations with scalars when nothing's been speci alized.
165 165
166 template <typename T> 166 template <typename T>
167 class SkNi<1,T> { 167 class SkNx<1,T> {
168 public: 168 public:
169 SkNi() {} 169 SkNx() {}
170 SkNi(T val) : fVal(val) {} 170 SkNx(T val) : fVal(val) {}
171 static SkNi Load(const T vals[1]) { return SkNi(vals[0]); } 171 static SkNx Load(const T vals[1]) { return SkNx(vals[0]); }
172 172
173 void store(T vals[1]) const { vals[0] = fVal; } 173 void store(T vals[1]) const { vals[0] = fVal; }
174 174
175 SkNi saturatedAdd(const SkNi& o) const { 175 SkNx saturatedAdd(const SkNx& o) const {
176 SkASSERT((T)(~0) > 0); // TODO: support signed T 176 SkASSERT((T)(~0) > 0); // TODO: support signed T
177 T sum = fVal + o.fVal; 177 T sum = fVal + o.fVal;
178 return SkNi(sum < fVal ? (T)(~0) : sum); 178 return SkNx(sum < fVal ? (T)(~0) : sum);
179 } 179 }
180 180
181 SkNi operator + (const SkNi& o) const { return SkNi(fVal + o.fVal); } 181 SkNx operator + (const SkNx& o) const { return SkNx(fVal + o.fVal); }
182 SkNi operator - (const SkNi& o) const { return SkNi(fVal - o.fVal); } 182 SkNx operator - (const SkNx& o) const { return SkNx(fVal - o.fVal); }
183 SkNi operator * (const SkNi& o) const { return SkNi(fVal * o.fVal); } 183 SkNx operator * (const SkNx& o) const { return SkNx(fVal * o.fVal); }
184 184
185 SkNi operator << (int bits) const { return SkNi(fVal << bits); } 185 SkNx operator << (int bits) const { return SkNx(fVal << bits); }
186 SkNi operator >> (int bits) const { return SkNi(fVal >> bits); } 186 SkNx operator >> (int bits) const { return SkNx(fVal >> bits); }
187 187
188 static SkNi Min(const SkNi& a, const SkNi& b) { return SkNi(SkTMin(a.fVal, b .fVal)); } 188 static SkNx Min(const SkNx& a, const SkNx& b) { return SkNx(SkTMin(a.fVal, b .fVal)); }
189 SkNi operator <(const SkNi& o) const { return SkNi(fVal < o.fVal); } 189 SkNx operator <(const SkNx& o) const { return SkNx(fVal < o.fVal); }
190 190
191 template <int k> T kth() const { 191 template <int k> T kth() const {
192 SkASSERT(0 == k); 192 SkASSERT(0 == k);
193 return fVal; 193 return fVal;
194 } 194 }
195 195
196 bool allTrue() const { return fVal; } 196 bool allTrue() const { return fVal; }
197 bool anyTrue() const { return fVal; } 197 bool anyTrue() const { return fVal; }
198 SkNi thenElse(const SkNi& t, const SkNi& e) const { return fVal ? t : e; } 198 SkNx thenElse(const SkNx& t, const SkNx& e) const { return fVal ? t : e; }
199 199
200 protected: 200 protected:
201 T fVal; 201 T fVal;
202 }; 202 };
203 203
204 template <> 204 template <>
205 class SkNf<1> { 205 class SkNx<1,float> {
206 public: 206 public:
207 SkNf() {} 207 SkNx() {}
208 SkNf(float val) : fVal(val) {} 208 SkNx(float val) : fVal(val) {}
209 static SkNf Load(const float vals[1]) { return SkNf(vals[0]); } 209 static SkNx Load(const float vals[1]) { return SkNx(vals[0]); }
210 static SkNf FromBytes(const uint8_t bytes[1]) { return SkNf((float)bytes[0]) ; } 210 static SkNx FromBytes(const uint8_t bytes[1]) { return SkNx((float)bytes[0]) ; }
211 211
212 void store(float vals[1]) const { vals[0] = fVal; } 212 void store(float vals[1]) const { vals[0] = fVal; }
213 void toBytes(uint8_t bytes[1]) const { bytes[0] = (uint8_t)(SkTMin(fVal, 255 .0f)); } 213 void toBytes(uint8_t bytes[1]) const { bytes[0] = (uint8_t)(SkTMin(fVal, 255 .0f)); }
214 214
215 SkNf operator + (const SkNf& o) const { return SkNf(fVal + o.fVal); } 215 SkNx operator + (const SkNx& o) const { return SkNx(fVal + o.fVal); }
216 SkNf operator - (const SkNf& o) const { return SkNf(fVal - o.fVal); } 216 SkNx operator - (const SkNx& o) const { return SkNx(fVal - o.fVal); }
217 SkNf operator * (const SkNf& o) const { return SkNf(fVal * o.fVal); } 217 SkNx operator * (const SkNx& o) const { return SkNx(fVal * o.fVal); }
218 SkNf operator / (const SkNf& o) const { return SkNf(fVal / o.fVal); } 218 SkNx operator / (const SkNx& o) const { return SkNx(fVal / o.fVal); }
219 219
220 SkNf operator == (const SkNf& o) const { return SkNf(fVal == o.fVal); } 220 SkNx operator == (const SkNx& o) const { return SkNx(fVal == o.fVal); }
221 SkNf operator != (const SkNf& o) const { return SkNf(fVal != o.fVal); } 221 SkNx operator != (const SkNx& o) const { return SkNx(fVal != o.fVal); }
222 SkNf operator < (const SkNf& o) const { return SkNf(fVal < o.fVal); } 222 SkNx operator < (const SkNx& o) const { return SkNx(fVal < o.fVal); }
223 SkNf operator > (const SkNf& o) const { return SkNf(fVal > o.fVal); } 223 SkNx operator > (const SkNx& o) const { return SkNx(fVal > o.fVal); }
224 SkNf operator <= (const SkNf& o) const { return SkNf(fVal <= o.fVal); } 224 SkNx operator <= (const SkNx& o) const { return SkNx(fVal <= o.fVal); }
225 SkNf operator >= (const SkNf& o) const { return SkNf(fVal >= o.fVal); } 225 SkNx operator >= (const SkNx& o) const { return SkNx(fVal >= o.fVal); }
226 226
227 static SkNf Min(const SkNf& l, const SkNf& r) { return SkNf(SkTMin(l.fVal, r .fVal)); } 227 static SkNx Min(const SkNx& l, const SkNx& r) { return SkNx(SkTMin(l.fVal, r .fVal)); }
228 static SkNf Max(const SkNf& l, const SkNf& r) { return SkNf(SkTMax(l.fVal, r .fVal)); } 228 static SkNx Max(const SkNx& l, const SkNx& r) { return SkNx(SkTMax(l.fVal, r .fVal)); }
229 229
230 SkNf sqrt() const { return SkNf(sqrtf(fVal)); } 230 SkNx sqrt() const { return SkNx(sqrtf(fVal)); }
231 SkNf rsqrt0() const { return SkNf(1.0f / sqrtf(fVal)); } 231 SkNx rsqrt0() const { return SkNx(1.0f / sqrtf(fVal)); }
232 SkNf rsqrt1() const { return this->rsqrt0(); } 232 SkNx rsqrt1() const { return this->rsqrt0(); }
233 SkNf rsqrt2() const { return this->rsqrt1(); } 233 SkNx rsqrt2() const { return this->rsqrt1(); }
234 234
235 SkNf invert() const { return SkNf(1.0f / fVal); } 235 SkNx invert() const { return SkNx(1.0f / fVal); }
236 SkNf approxInvert() const { return this->invert(); } 236 SkNx approxInvert() const { return this->invert(); }
237 237
238 template <int k> float kth() const { 238 template <int k> float kth() const {
239 SkASSERT(k == 0); 239 SkASSERT(k == 0);
240 return fVal; 240 return fVal;
241 } 241 }
242 242
243 bool allTrue() const { return this->pun() != 0; } 243 bool allTrue() const { return this->pun() != 0; }
244 bool anyTrue() const { return this->pun() != 0; } 244 bool anyTrue() const { return this->pun() != 0; }
245 SkNf thenElse(const SkNf& t, const SkNf& e) const { return this->pun() ? t : e; } 245 SkNx thenElse(const SkNx& t, const SkNx& e) const { return this->pun() ? t : e; }
246 246
247 protected: 247 protected:
248 uint32_t pun() const { 248 uint32_t pun() const {
249 union { float f; uint32_t i; } pun = { fVal }; 249 union { float f; uint32_t i; } pun = { fVal };
250 return pun.i; 250 return pun.i;
251 } 251 }
252 252
253 float fVal; 253 float fVal;
254 }; 254 };
255 255
256 // This default implementation can be specialized by ../opts/SkNx_foo.h 256 // This default implementation can be specialized by ../opts/SkNx_foo.h
257 // if there's a better platform-specific shuffle strategy. 257 // if there's a better platform-specific shuffle strategy.
258 template <typename SkNx, int... Ix> 258 template <typename Nx, int... Ix>
259 inline SkNx SkNx_shuffle_impl(const SkNx& src) { return SkNx( src.template kth<I x>()... ); } 259 inline Nx SkNx_shuffle_impl(const Nx& src) { return Nx( src.template kth<Ix>().. . ); }
260 260
261 // This generic shuffle can be called on either SkNi or SkNf with 1 or N indices : 261 // This generic shuffle can be called with 1 or N indices:
262 // Sk4f f(a,b,c,d); 262 // Sk4f f(a,b,c,d);
263 // SkNx_shuffle<3>(f); // ~~~> Sk4f(d,d,d,d) 263 // SkNx_shuffle<3>(f); // ~~~> Sk4f(d,d,d,d)
264 // SkNx_shuffle<2,1,0,3>(f); // ~~~> Sk4f(c,b,a,d) 264 // SkNx_shuffle<2,1,0,3>(f); // ~~~> Sk4f(c,b,a,d)
265 template <int... Ix, typename SkNx> 265 template <int... Ix, typename Nx>
266 inline SkNx SkNx_shuffle(const SkNx& src) { return SkNx_shuffle_impl<SkNx, Ix... >(src); } 266 inline Nx SkNx_shuffle(const Nx& src) { return SkNx_shuffle_impl<Nx, Ix...>(src) ; }
267 267
268 // A reminder alias that shuffles can be used to duplicate a single index across a vector. 268 // A reminder alias that shuffles can be used to duplicate a single index across a vector.
269 template <int Ix, typename SkNx> 269 template <int Ix, typename Nx>
270 inline SkNx SkNx_dup(const SkNx& src) { return SkNx_shuffle<Ix>(src); } 270 inline Nx SkNx_dup(const Nx& src) { return SkNx_shuffle<Ix>(src); }
271
272 // This is a poor-man's std::make_index_sequence from C++14.
273 // I'd implement it fully, but it hurts my head.
274 template <int...> struct SkIntSequence {};
275 template <int N> struct MakeSkIntSequence;
276 template <> struct MakeSkIntSequence< 1> : SkIntSequence<0 >{};
277 template <> struct MakeSkIntSequence< 2> : SkIntSequence<0,1 >{};
278 template <> struct MakeSkIntSequence< 4> : SkIntSequence<0,1,2,3 >{};
279 template <> struct MakeSkIntSequence< 8> : SkIntSequence<0,1,2,3,4,5,6,7 >{};
280 template <> struct MakeSkIntSequence<16> : SkIntSequence<0,1,2,3,4,5,6,7,8,9,10, 11,12,13,14,15>{};
281
282 // This is the default/fallback implementation for SkNx_cast. Best to specializ e SkNx_cast!
283 template <typename D, typename S, int N, int... Ix>
284 SkNx<N,D> SkNx_cast_fallback(const SkNx<N,S>& src, SkIntSequence<Ix...>) {
285 return SkNx<N,D>( (D)src.template kth<Ix>()... );
286 }
287
288 // This is a generic cast between two SkNx with the same number of elements N. E.g.
289 // Sk4b bs = ...; // Load 4 bytes.
290 // Sk4f fs = SkNx_cast<float>(bs); // (This will replace SkNf::FromBytes() o ne day.)
291 // Sk4i is = SkNx_cast<int>(fs); // Cast each float to int.
292 // This can be specialized in ../opts/SkNx_foo.h if there's a better platform-sp ecific cast.
293 template <typename D, typename S, int N>
294 SkNx<N,D> SkNx_cast(const SkNx<N,S>& src) {
295 return SkNx_cast_fallback<D,S,N>(src, MakeSkIntSequence<N>());
296 }
271 297
272 } // namespace 298 } // namespace
273 299
274 300
275 // Include platform specific specializations if available. 301 // Include platform specific specializations if available.
276 #ifndef SKNX_NO_SIMD 302 #ifndef SKNX_NO_SIMD
277 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_AVX 303 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_AVX
278 #include "../opts/SkNx_avx.h" 304 #include "../opts/SkNx_avx.h"
279 #elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 305 #elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
280 #include "../opts/SkNx_sse.h" 306 #include "../opts/SkNx_sse.h"
281 #elif defined(SK_ARM_HAS_NEON) 307 #elif defined(SK_ARM_HAS_NEON)
282 #include "../opts/SkNx_neon.h" 308 #include "../opts/SkNx_neon.h"
283 #endif 309 #endif
284 #endif 310 #endif
285 311
286 #undef REQUIRE 312 #undef REQUIRE
287 313
288 typedef SkNf<2> Sk2f; 314 typedef SkNx<2, float> Sk2f;
289 typedef SkNf<2> Sk2s; 315 typedef SkNx<2, float> Sk2s;
290 typedef SkNf<4> Sk4f; 316 typedef SkNx<4, float> Sk4f;
291 typedef SkNf<4> Sk4s; 317 typedef SkNx<4, float> Sk4s;
292 typedef SkNf<8> Sk8f; 318 typedef SkNx<8, float> Sk8f;
293 typedef SkNf<8> Sk8s; 319 typedef SkNx<8, float> Sk8s;
294 320
295 typedef SkNi<8, uint16_t> Sk8h; 321 typedef SkNx<8, uint16_t> Sk8h;
296 typedef SkNi<16, uint16_t> Sk16h; 322 typedef SkNx<16, uint16_t> Sk16h;
297 typedef SkNi<16, uint8_t> Sk16b; 323 typedef SkNx<16, uint8_t> Sk16b;
324
325 typedef SkNx<4, int> Sk4i;
298 326
299 #endif//SkNx_DEFINED 327 #endif//SkNx_DEFINED
OLDNEW
« no previous file with comments | « no previous file | src/opts/SkNx_avx.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698