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 #include "Sk4px.h" | 8 #include "Sk4px.h" |
9 #include "SkNx.h" | 9 #include "SkNx.h" |
10 #include "SkRandom.h" | 10 #include "SkRandom.h" |
11 #include "Test.h" | 11 #include "Test.h" |
12 | 12 |
13 template <int N> | 13 template <int N> |
14 static void test_Nf(skiatest::Reporter* r) { | 14 static void test_Nf(skiatest::Reporter* r) { |
15 | 15 |
16 auto assert_nearly_eq = [&](float eps, const SkNx<N, float>& v, | 16 auto assert_nearly_eq = [&](float eps, const SkNx<N, float>& v, |
17 float a, float b, float c, float d) { | 17 float a, float b, float c, float d) { |
18 auto close = [=](float a, float b) { return fabsf(a-b) <= eps; }; | 18 auto close = [=](float a, float b) { return fabsf(a-b) <= eps; }; |
19 float vals[4]; | 19 float vals[4]; |
20 v.store(vals); | 20 v.store(vals); |
21 bool ok = close(vals[0], a) && close(vals[1], b) | 21 bool ok = close(vals[0], a) && close(vals[1], b) |
22 && close(v.template kth<0>(), a) && close(v.template kth<1>(), b)
; | 22 && close( v[0], a) && close( v[1], b); |
23 REPORTER_ASSERT(r, ok); | 23 REPORTER_ASSERT(r, ok); |
24 if (N == 4) { | 24 if (N == 4) { |
25 ok = close(vals[2], c) && close(vals[3], d) | 25 ok = close(vals[2], c) && close(vals[3], d) |
26 && close(v.template kth<2>(), c) && close(v.template kth<3>(), d); | 26 && close( v[2], c) && close( v[3], d); |
27 REPORTER_ASSERT(r, ok); | 27 REPORTER_ASSERT(r, ok); |
28 } | 28 } |
29 }; | 29 }; |
30 auto assert_eq = [&](const SkNx<N, float>& v, float a, float b, float c, flo
at d) { | 30 auto assert_eq = [&](const SkNx<N, float>& v, float a, float b, float c, flo
at d) { |
31 return assert_nearly_eq(0, v, a,b,c,d); | 31 return assert_nearly_eq(0, v, a,b,c,d); |
32 }; | 32 }; |
33 | 33 |
34 float vals[] = {3, 4, 5, 6}; | 34 float vals[] = {3, 4, 5, 6}; |
35 SkNx<N,float> a = SkNx<N,float>::Load(vals), | 35 SkNx<N,float> a = SkNx<N,float>::Load(vals), |
36 b(a), | 36 b(a), |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 auto assert_eq = [&](const SkNx<N,T>& v, T a, T b, T c, T d, T e, T f, T g,
T h) { | 85 auto assert_eq = [&](const SkNx<N,T>& v, T a, T b, T c, T d, T e, T f, T g,
T h) { |
86 T vals[8]; | 86 T vals[8]; |
87 v.store(vals); | 87 v.store(vals); |
88 | 88 |
89 switch (N) { | 89 switch (N) { |
90 case 8: REPORTER_ASSERT(r, vals[4] == e && vals[5] == f && vals[6] ==
g && vals[7] == h); | 90 case 8: REPORTER_ASSERT(r, vals[4] == e && vals[5] == f && vals[6] ==
g && vals[7] == h); |
91 case 4: REPORTER_ASSERT(r, vals[2] == c && vals[3] == d); | 91 case 4: REPORTER_ASSERT(r, vals[2] == c && vals[3] == d); |
92 case 2: REPORTER_ASSERT(r, vals[0] == a && vals[1] == b); | 92 case 2: REPORTER_ASSERT(r, vals[0] == a && vals[1] == b); |
93 } | 93 } |
94 switch (N) { | 94 switch (N) { |
95 case 8: REPORTER_ASSERT(r, v.template kth<4>() == e && v.template kth<
5>() == f && | 95 case 8: REPORTER_ASSERT(r, v[4] == e && v[5] == f && |
96 v.template kth<6>() == g && v.template kth<
7>() == h); | 96 v[6] == g && v[7] == h); |
97 case 4: REPORTER_ASSERT(r, v.template kth<2>() == c && v.template kth<
3>() == d); | 97 case 4: REPORTER_ASSERT(r, v[2] == c && v[3] == d); |
98 case 2: REPORTER_ASSERT(r, v.template kth<0>() == a && v.template kth<
1>() == b); | 98 case 2: REPORTER_ASSERT(r, v[0] == a && v[1] == b); |
99 } | 99 } |
100 }; | 100 }; |
101 | 101 |
102 T vals[] = { 1,2,3,4,5,6,7,8 }; | 102 T vals[] = { 1,2,3,4,5,6,7,8 }; |
103 SkNx<N,T> a = SkNx<N,T>::Load(vals), | 103 SkNx<N,T> a = SkNx<N,T>::Load(vals), |
104 b(a), | 104 b(a), |
105 c = a; | 105 c = a; |
106 SkNx<N,T> d; | 106 SkNx<N,T> d; |
107 d = a; | 107 d = a; |
108 | 108 |
109 assert_eq(a, 1,2,3,4,5,6,7,8); | 109 assert_eq(a, 1,2,3,4,5,6,7,8); |
110 assert_eq(b, 1,2,3,4,5,6,7,8); | 110 assert_eq(b, 1,2,3,4,5,6,7,8); |
111 assert_eq(c, 1,2,3,4,5,6,7,8); | 111 assert_eq(c, 1,2,3,4,5,6,7,8); |
112 assert_eq(d, 1,2,3,4,5,6,7,8); | 112 assert_eq(d, 1,2,3,4,5,6,7,8); |
113 | 113 |
114 assert_eq(a+a, 2,4,6,8,10,12,14,16); | 114 assert_eq(a+a, 2,4,6,8,10,12,14,16); |
115 assert_eq(a*a, 1,4,9,16,25,36,49,64); | 115 assert_eq(a*a, 1,4,9,16,25,36,49,64); |
116 assert_eq(a*a-a, 0,2,6,12,20,30,42,56); | 116 assert_eq(a*a-a, 0,2,6,12,20,30,42,56); |
117 | 117 |
118 assert_eq(a >> 2, 0,0,0,1,1,1,1,2); | 118 assert_eq(a >> 2, 0,0,0,1,1,1,1,2); |
119 assert_eq(a << 1, 2,4,6,8,10,12,14,16); | 119 assert_eq(a << 1, 2,4,6,8,10,12,14,16); |
120 | 120 |
121 REPORTER_ASSERT(r, a.template kth<1>() == 2); | 121 REPORTER_ASSERT(r, a[1] == 2); |
122 } | 122 } |
123 | 123 |
124 DEF_TEST(SkNx, r) { | 124 DEF_TEST(SkNx, r) { |
125 test_Ni<2, uint16_t>(r); | 125 test_Ni<2, uint16_t>(r); |
126 test_Ni<4, uint16_t>(r); | 126 test_Ni<4, uint16_t>(r); |
127 test_Ni<8, uint16_t>(r); | 127 test_Ni<8, uint16_t>(r); |
128 | 128 |
129 test_Ni<2, int>(r); | 129 test_Ni<2, int>(r); |
130 test_Ni<4, int>(r); | 130 test_Ni<4, int>(r); |
131 test_Ni<8, int>(r); | 131 test_Ni<8, int>(r); |
132 } | 132 } |
133 | 133 |
134 DEF_TEST(SkNi_min_lt, r) { | 134 DEF_TEST(SkNi_min_lt, r) { |
135 // Exhaustively check the 8x8 bit space. | 135 // Exhaustively check the 8x8 bit space. |
136 for (int a = 0; a < (1<<8); a++) { | 136 for (int a = 0; a < (1<<8); a++) { |
137 for (int b = 0; b < (1<<8); b++) { | 137 for (int b = 0; b < (1<<8); b++) { |
138 Sk16b aw(a), bw(b); | 138 Sk16b aw(a), bw(b); |
139 REPORTER_ASSERT(r, Sk16b::Min(aw, bw).kth<0>() == SkTMin(a, b)); | 139 REPORTER_ASSERT(r, Sk16b::Min(aw, bw)[0] == SkTMin(a, b)); |
140 REPORTER_ASSERT(r, !(aw < bw).kth<0>() == !(a < b)); | 140 REPORTER_ASSERT(r, !(aw < bw)[0] == !(a < b)); |
141 }} | 141 }} |
142 | 142 |
143 // Exhausting the 16x16 bit space is kind of slow, so only do that in releas
e builds. | 143 // Exhausting the 16x16 bit space is kind of slow, so only do that in releas
e builds. |
144 #ifdef SK_DEBUG | 144 #ifdef SK_DEBUG |
145 SkRandom rand; | 145 SkRandom rand; |
146 for (int i = 0; i < (1<<16); i++) { | 146 for (int i = 0; i < (1<<16); i++) { |
147 uint16_t a = rand.nextU() >> 16, | 147 uint16_t a = rand.nextU() >> 16, |
148 b = rand.nextU() >> 16; | 148 b = rand.nextU() >> 16; |
149 REPORTER_ASSERT(r, Sk16h::Min(Sk16h(a), Sk16h(b)).kth<0>() == SkTMin(a,
b)); | 149 REPORTER_ASSERT(r, Sk16h::Min(Sk16h(a), Sk16h(b))[0] == SkTMin(a, b)); |
150 } | 150 } |
151 #else | 151 #else |
152 for (int a = 0; a < (1<<16); a++) { | 152 for (int a = 0; a < (1<<16); a++) { |
153 for (int b = 0; b < (1<<16); b++) { | 153 for (int b = 0; b < (1<<16); b++) { |
154 REPORTER_ASSERT(r, Sk16h::Min(Sk16h(a), Sk16h(b)).kth<0>() == SkTMin(a,
b)); | 154 REPORTER_ASSERT(r, Sk16h::Min(Sk16h(a), Sk16h(b))[0] == SkTMin(a, b)); |
155 }} | 155 }} |
156 #endif | 156 #endif |
157 } | 157 } |
158 | 158 |
159 DEF_TEST(SkNi_saturatedAdd, r) { | 159 DEF_TEST(SkNi_saturatedAdd, r) { |
160 for (int a = 0; a < (1<<8); a++) { | 160 for (int a = 0; a < (1<<8); a++) { |
161 for (int b = 0; b < (1<<8); b++) { | 161 for (int b = 0; b < (1<<8); b++) { |
162 int exact = a+b; | 162 int exact = a+b; |
163 if (exact > 255) { exact = 255; } | 163 if (exact > 255) { exact = 255; } |
164 if (exact < 0) { exact = 0; } | 164 if (exact < 0) { exact = 0; } |
165 | 165 |
166 REPORTER_ASSERT(r, Sk16b(a).saturatedAdd(Sk16b(b)).kth<0>() == exact); | 166 REPORTER_ASSERT(r, Sk16b(a).saturatedAdd(Sk16b(b))[0] == exact); |
167 } | 167 } |
168 } | 168 } |
169 } | 169 } |
170 | 170 |
171 DEF_TEST(Sk4px_muldiv255round, r) { | 171 DEF_TEST(Sk4px_muldiv255round, r) { |
172 for (int a = 0; a < (1<<8); a++) { | 172 for (int a = 0; a < (1<<8); a++) { |
173 for (int b = 0; b < (1<<8); b++) { | 173 for (int b = 0; b < (1<<8); b++) { |
174 int exact = (a*b+127)/255; | 174 int exact = (a*b+127)/255; |
175 | 175 |
176 // Duplicate a and b 16x each. | 176 // Duplicate a and b 16x each. |
177 auto av = Sk4px::DupAlpha(a), | 177 auto av = Sk4px::DupAlpha(a), |
178 bv = Sk4px::DupAlpha(b); | 178 bv = Sk4px::DupAlpha(b); |
179 | 179 |
180 // This way should always be exactly correct. | 180 // This way should always be exactly correct. |
181 int correct = (av * bv).div255().kth<0>(); | 181 int correct = (av * bv).div255()[0]; |
182 REPORTER_ASSERT(r, correct == exact); | 182 REPORTER_ASSERT(r, correct == exact); |
183 | 183 |
184 // We're a bit more flexible on this method: correct for 0 or 255, other
wise off by <=1. | 184 // We're a bit more flexible on this method: correct for 0 or 255, other
wise off by <=1. |
185 int fast = av.approxMulDiv255(bv).kth<0>(); | 185 int fast = av.approxMulDiv255(bv)[0]; |
186 REPORTER_ASSERT(r, fast-exact >= -1 && fast-exact <= 1); | 186 REPORTER_ASSERT(r, fast-exact >= -1 && fast-exact <= 1); |
187 if (a == 0 || a == 255 || b == 0 || b == 255) { | 187 if (a == 0 || a == 255 || b == 0 || b == 255) { |
188 REPORTER_ASSERT(r, fast == exact); | 188 REPORTER_ASSERT(r, fast == exact); |
189 } | 189 } |
190 } | 190 } |
191 } | 191 } |
192 } | 192 } |
193 | 193 |
194 DEF_TEST(Sk4px_widening, r) { | 194 DEF_TEST(Sk4px_widening, r) { |
195 SkPMColor colors[] = { | 195 SkPMColor colors[] = { |
196 SkPreMultiplyColor(0xff00ff00), | 196 SkPreMultiplyColor(0xff00ff00), |
197 SkPreMultiplyColor(0x40008000), | 197 SkPreMultiplyColor(0x40008000), |
198 SkPreMultiplyColor(0x7f020406), | 198 SkPreMultiplyColor(0x7f020406), |
199 SkPreMultiplyColor(0x00000000), | 199 SkPreMultiplyColor(0x00000000), |
200 }; | 200 }; |
201 auto packed = Sk4px::Load4(colors); | 201 auto packed = Sk4px::Load4(colors); |
202 | 202 |
203 auto wideLo = packed.widenLo(), | 203 auto wideLo = packed.widenLo(), |
204 wideHi = packed.widenHi(), | 204 wideHi = packed.widenHi(), |
205 wideLoHi = packed.widenLoHi(), | 205 wideLoHi = packed.widenLoHi(), |
206 wideLoHiAlt = wideLo + wideHi; | 206 wideLoHiAlt = wideLo + wideHi; |
207 REPORTER_ASSERT(r, 0 == memcmp(&wideLoHi, &wideLoHiAlt, sizeof(wideLoHi))); | 207 REPORTER_ASSERT(r, 0 == memcmp(&wideLoHi, &wideLoHiAlt, sizeof(wideLoHi))); |
208 } | 208 } |
209 | 209 |
210 DEF_TEST(SkNx_abs, r) { | 210 DEF_TEST(SkNx_abs, r) { |
211 auto fs = Sk4f(0.0f, -0.0f, 2.0f, -4.0f).abs(); | 211 auto fs = Sk4f(0.0f, -0.0f, 2.0f, -4.0f).abs(); |
212 REPORTER_ASSERT(r, fs.kth<0>() == 0.0f); | 212 REPORTER_ASSERT(r, fs[0] == 0.0f); |
213 REPORTER_ASSERT(r, fs.kth<1>() == 0.0f); | 213 REPORTER_ASSERT(r, fs[1] == 0.0f); |
214 REPORTER_ASSERT(r, fs.kth<2>() == 2.0f); | 214 REPORTER_ASSERT(r, fs[2] == 2.0f); |
215 REPORTER_ASSERT(r, fs.kth<3>() == 4.0f); | 215 REPORTER_ASSERT(r, fs[3] == 4.0f); |
216 } | 216 } |
217 | 217 |
218 DEF_TEST(SkNx_floor, r) { | 218 DEF_TEST(SkNx_floor, r) { |
219 auto fs = Sk4f(0.4f, -0.4f, 0.6f, -0.6f).floor(); | 219 auto fs = Sk4f(0.4f, -0.4f, 0.6f, -0.6f).floor(); |
220 REPORTER_ASSERT(r, fs.kth<0>() == 0.0f); | 220 REPORTER_ASSERT(r, fs[0] == 0.0f); |
221 REPORTER_ASSERT(r, fs.kth<1>() == -1.0f); | 221 REPORTER_ASSERT(r, fs[1] == -1.0f); |
222 REPORTER_ASSERT(r, fs.kth<2>() == 0.0f); | 222 REPORTER_ASSERT(r, fs[2] == 0.0f); |
223 REPORTER_ASSERT(r, fs.kth<3>() == -1.0f); | 223 REPORTER_ASSERT(r, fs[3] == -1.0f); |
224 } | 224 } |
225 | 225 |
226 DEF_TEST(SkNx_shuffle, r) { | 226 DEF_TEST(SkNx_shuffle, r) { |
227 Sk4f f4(0,10,20,30); | 227 Sk4f f4(0,10,20,30); |
228 | 228 |
229 Sk2f f2 = SkNx_shuffle<2,1>(f4); | 229 Sk2f f2 = SkNx_shuffle<2,1>(f4); |
230 REPORTER_ASSERT(r, f2[0] == 20); | 230 REPORTER_ASSERT(r, f2[0] == 20); |
231 REPORTER_ASSERT(r, f2[1] == 10); | 231 REPORTER_ASSERT(r, f2[1] == 10); |
232 | 232 |
233 f4 = SkNx_shuffle<0,1,1,0>(f2); | 233 f4 = SkNx_shuffle<0,1,1,0>(f2); |
(...skipping 19 matching lines...) Expand all Loading... |
253 REPORTER_ASSERT(r, f[3] == 0.0f); | 253 REPORTER_ASSERT(r, f[3] == 0.0f); |
254 } | 254 } |
255 | 255 |
256 #include "SkRandom.h" | 256 #include "SkRandom.h" |
257 | 257 |
258 DEF_TEST(SkNx_u16_float, r) { | 258 DEF_TEST(SkNx_u16_float, r) { |
259 { | 259 { |
260 // u16 --> float | 260 // u16 --> float |
261 auto h4 = Sk4h(15, 17, 257, 65535); | 261 auto h4 = Sk4h(15, 17, 257, 65535); |
262 auto f4 = SkNx_cast<float>(h4); | 262 auto f4 = SkNx_cast<float>(h4); |
263 REPORTER_ASSERT(r, f4.kth<0>() == 15.0f); | 263 REPORTER_ASSERT(r, f4[0] == 15.0f); |
264 REPORTER_ASSERT(r, f4.kth<1>() == 17.0f); | 264 REPORTER_ASSERT(r, f4[1] == 17.0f); |
265 REPORTER_ASSERT(r, f4.kth<2>() == 257.0f); | 265 REPORTER_ASSERT(r, f4[2] == 257.0f); |
266 REPORTER_ASSERT(r, f4.kth<3>() == 65535.0f); | 266 REPORTER_ASSERT(r, f4[3] == 65535.0f); |
267 } | 267 } |
268 { | 268 { |
269 // float -> u16 | 269 // float -> u16 |
270 auto f4 = Sk4f(15, 17, 257, 65535); | 270 auto f4 = Sk4f(15, 17, 257, 65535); |
271 auto h4 = SkNx_cast<uint16_t>(f4); | 271 auto h4 = SkNx_cast<uint16_t>(f4); |
272 REPORTER_ASSERT(r, h4.kth<0>() == 15); | 272 REPORTER_ASSERT(r, h4[0] == 15); |
273 REPORTER_ASSERT(r, h4.kth<1>() == 17); | 273 REPORTER_ASSERT(r, h4[1] == 17); |
274 REPORTER_ASSERT(r, h4.kth<2>() == 257); | 274 REPORTER_ASSERT(r, h4[2] == 257); |
275 REPORTER_ASSERT(r, h4.kth<3>() == 65535); | 275 REPORTER_ASSERT(r, h4[3] == 65535); |
276 } | 276 } |
277 | 277 |
278 // starting with any u16 value, we should be able to have a perfect round-tr
ip in/out of floats | 278 // starting with any u16 value, we should be able to have a perfect round-tr
ip in/out of floats |
279 // | 279 // |
280 SkRandom rand; | 280 SkRandom rand; |
281 for (int i = 0; i < 10000; ++i) { | 281 for (int i = 0; i < 10000; ++i) { |
282 const uint16_t s16[4] { | 282 const uint16_t s16[4] { |
283 (uint16_t)rand.nextU16(), (uint16_t)rand.nextU16(), | 283 (uint16_t)rand.nextU16(), (uint16_t)rand.nextU16(), |
284 (uint16_t)rand.nextU16(), (uint16_t)rand.nextU16(), | 284 (uint16_t)rand.nextU16(), (uint16_t)rand.nextU16(), |
285 }; | 285 }; |
286 auto u4_0 = Sk4h::Load(s16); | 286 auto u4_0 = Sk4h::Load(s16); |
287 auto f4 = SkNx_cast<float>(u4_0); | 287 auto f4 = SkNx_cast<float>(u4_0); |
288 auto u4_1 = SkNx_cast<uint16_t>(f4); | 288 auto u4_1 = SkNx_cast<uint16_t>(f4); |
289 uint16_t d16[4]; | 289 uint16_t d16[4]; |
290 u4_1.store(d16); | 290 u4_1.store(d16); |
291 REPORTER_ASSERT(r, !memcmp(s16, d16, sizeof(s16))); | 291 REPORTER_ASSERT(r, !memcmp(s16, d16, sizeof(s16))); |
292 } | 292 } |
293 } | 293 } |
OLD | NEW |