• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "src/core/SkOpts.h"
9 #include "tests/Test.h"
10 
11 #include <algorithm>
12 #include <array>
13 #include <cstddef>
14 
15 #define SK_OPTS_NS RPOptsTest
16 
17 #if defined(__clang__)
18 #pragma clang diagnostic push
19 #pragma clang diagnostic ignored "-Wunused-function"
20 #elif defined(__GNUC__)
21 #pragma GCC diagnostic push
22 #pragma GCC diagnostic ignored "-Wunused-function"
23 #pragma GCC diagnostic ignored "-Wunused-variable"
24 #endif
25 
26 #include "src/opts/SkRasterPipeline_opts.h"
27 
28 #if defined(__clang__)
29 #pragma clang diagnostic pop
30 #elif defined(__GNUC__)
31 #pragma GCC diagnostic pop
32 #endif
33 
34 template <size_t N>
make_masks(int bits)35 static std::array<int32_t, N> make_masks(int bits) {
36     // Make an array of masks that correspond to the bit pattern of `bits`.
37     std::array<int32_t, N> masks;
38     for (size_t idx = 0; idx < N; ++idx) {
39         masks[idx] = (bits & 1) ? ~0 : 0;
40         bits >>= 1;
41     }
42     SkASSERT(!bits);
43     return masks;
44 }
45 
DEF_TEST(SkRasterPipelineOpts_Any,r)46 DEF_TEST(SkRasterPipelineOpts_Any, r) {
47     using I32 = SK_OPTS_NS::I32;
48     static constexpr size_t N = sizeof(I32) / sizeof(int32_t);
49 
50     for (int value = 0; value < (1 << N); ++value) {
51         // Load masks corresponding to the bit-pattern of `value` into lanes of `i`.
52         std::array<int32_t, N> masks = make_masks<N>(value);
53         I32 i = sk_unaligned_load<I32>(masks.data());
54 
55         // Verify that the raster pipeline any() matches expectations.
56         REPORTER_ASSERT(r, SK_OPTS_NS::any(i) == std::any_of(masks.begin(), masks.end(),
57                                                              [](int32_t m) { return m != 0; }));
58     }
59 }
60 
DEF_TEST(SkRasterPipelineOpts_All,r)61 DEF_TEST(SkRasterPipelineOpts_All, r) {
62     using I32 = SK_OPTS_NS::I32;
63     static constexpr size_t N = sizeof(I32) / sizeof(int32_t);
64 
65     for (int value = 0; value < (1 << N); ++value) {
66         // Load masks corresponding to the bit-pattern of `value` into lanes of `i`.
67         std::array<int32_t, N> masks = make_masks<N>(value);
68         I32 i = sk_unaligned_load<I32>(masks.data());
69 
70         // Verify that the raster pipeline all() matches expectations.
71         REPORTER_ASSERT(r, SK_OPTS_NS::all(i) == std::all_of(masks.begin(), masks.end(),
72                                                              [](int32_t m) { return m != 0; }));
73     }
74 }
75 
DEF_TEST(SkRasterPipelineOpts_Sin,r)76 DEF_TEST(SkRasterPipelineOpts_Sin, r) {
77     using F = SK_OPTS_NS::F;
78 
79     constexpr float Pi = SK_ScalarPI;
80     constexpr float kTolerance = 0.00175f;
81     for (float rad = -5*Pi; rad <= 5*Pi; rad += 0.1f) {
82         F result = SK_OPTS_NS::sin_(rad);
83         F expected = sk_float_sin(rad);
84         F delta = SK_OPTS_NS::abs_(expected - result);
85 
86         REPORTER_ASSERT(r, SK_OPTS_NS::all(delta < kTolerance));
87     }
88 }
89 
DEF_TEST(SkRasterPipelineOpts_Cos,r)90 DEF_TEST(SkRasterPipelineOpts_Cos, r) {
91     using F = SK_OPTS_NS::F;
92 
93     constexpr float Pi = SK_ScalarPI;
94     constexpr float kTolerance = 0.00175f;
95     for (float rad = -5*Pi; rad <= 5*Pi; rad += 0.1f) {
96         F result = SK_OPTS_NS::cos_(rad);
97         F expected = sk_float_cos(rad);
98         F delta = SK_OPTS_NS::abs_(expected - result);
99 
100         REPORTER_ASSERT(r, SK_OPTS_NS::all(delta < kTolerance));
101     }
102 }
103 
DEF_TEST(SkRasterPipelineOpts_Tan,r)104 DEF_TEST(SkRasterPipelineOpts_Tan, r) {
105     using F = SK_OPTS_NS::F;
106 
107     // Our tangent diverges more as we get near infinities (x near +- Pi/2),
108     // so we bring in the domain a little.
109     constexpr float Pi = SK_ScalarPI;
110     constexpr float kEpsilon = 0.16f;
111     constexpr float kTolerance = 0.00175f;
112 
113     // Test against various multiples of Pi, to check our periodicity
114     for (float period : {0.0f, -3*Pi, 3*Pi}) {
115         for (float rad = -Pi/2 + kEpsilon; rad <= Pi/2 - kEpsilon; rad += 0.01f) {
116             F result = SK_OPTS_NS::tan_(rad + period);
117             F expected = sk_float_tan(rad);
118             F delta = SK_OPTS_NS::abs_(expected - result);
119 
120             REPORTER_ASSERT(r, SK_OPTS_NS::all(delta < kTolerance));
121         }
122     }
123 }
124 
DEF_TEST(SkRasterPipelineOpts_Atan,r)125 DEF_TEST(SkRasterPipelineOpts_Atan, r) {
126     using F = SK_OPTS_NS::F;
127 
128     constexpr float kTolerance = 0.00175f;
129     for (float x = -10.0f; x <= 10.0f; x += 0.1f) {
130         F result = SK_OPTS_NS::atan_(x);
131         F expected = atanf(x);
132         F delta = SK_OPTS_NS::abs_(expected - result);
133 
134         REPORTER_ASSERT(r, SK_OPTS_NS::all(delta < kTolerance));
135     }
136 }
137 
DEF_TEST(SkRasterPipelineOpts_Atan2,r)138 DEF_TEST(SkRasterPipelineOpts_Atan2, r) {
139     using F = SK_OPTS_NS::F;
140 
141     constexpr float kTolerance = 0.00175f;
142     for (float y = -3.0f; y <= 3.0f; y += 0.1f) {
143         for (float x = -3.0f; x <= 3.0f; x += 0.1f) {
144             F result = SK_OPTS_NS::atan2_(y, x);
145             F expected = sk_float_atan2(y, x);
146             F delta = SK_OPTS_NS::abs_(expected - result);
147 
148             REPORTER_ASSERT(r, SK_OPTS_NS::all(delta < kTolerance));
149         }
150     }
151 }
152