blob: 438ee6b6aa01e4a1ffd084cc532e8dee7048096d [file] [log] [blame]
/*
* Copyright 2022 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/core/SkOpts.h"
#include "tests/Test.h"
#include <algorithm>
#include <array>
#include <cstddef>
#define SK_OPTS_NS RPOptsTest
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-function"
#elif defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#pragma GCC diagnostic ignored "-Wunused-variable"
#endif
#include "src/opts/SkRasterPipeline_opts.h"
#if defined(__clang__)
#pragma clang diagnostic pop
#elif defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
template <size_t N>
static std::array<int32_t, N> make_masks(int bits) {
// Make an array of masks that correspond to the bit pattern of `bits`.
std::array<int32_t, N> masks;
for (size_t idx = 0; idx < N; ++idx) {
masks[idx] = (bits & 1) ? ~0 : 0;
bits >>= 1;
}
SkASSERT(!bits);
return masks;
}
DEF_TEST(SkRasterPipelineOpts_Any, r) {
using I32 = SK_OPTS_NS::I32;
static constexpr size_t N = sizeof(I32) / sizeof(int32_t);
for (int value = 0; value < (1 << N); ++value) {
// Load masks corresponding to the bit-pattern of `value` into lanes of `i`.
std::array<int32_t, N> masks = make_masks<N>(value);
I32 i = sk_unaligned_load<I32>(masks.data());
// Verify that the raster pipeline any() matches expectations.
REPORTER_ASSERT(r, SK_OPTS_NS::any(i) == std::any_of(masks.begin(), masks.end(),
[](int32_t m) { return m != 0; }));
}
}
DEF_TEST(SkRasterPipelineOpts_All, r) {
using I32 = SK_OPTS_NS::I32;
static constexpr size_t N = sizeof(I32) / sizeof(int32_t);
for (int value = 0; value < (1 << N); ++value) {
// Load masks corresponding to the bit-pattern of `value` into lanes of `i`.
std::array<int32_t, N> masks = make_masks<N>(value);
I32 i = sk_unaligned_load<I32>(masks.data());
// Verify that the raster pipeline all() matches expectations.
REPORTER_ASSERT(r, SK_OPTS_NS::all(i) == std::all_of(masks.begin(), masks.end(),
[](int32_t m) { return m != 0; }));
}
}
DEF_TEST(SkRasterPipelineOpts_Sin, r) {
using F = SK_OPTS_NS::F;
constexpr float Pi = SK_ScalarPI;
constexpr float kTolerance = 0.00175f;
for (float rad = -5*Pi; rad <= 5*Pi; rad += 0.1f) {
F result = SK_OPTS_NS::sin_(rad);
F expected = sk_float_sin(rad);
F delta = SK_OPTS_NS::abs_(expected - result);
REPORTER_ASSERT(r, SK_OPTS_NS::all(delta < kTolerance));
}
}
DEF_TEST(SkRasterPipelineOpts_Cos, r) {
using F = SK_OPTS_NS::F;
constexpr float Pi = SK_ScalarPI;
constexpr float kTolerance = 0.00175f;
for (float rad = -5*Pi; rad <= 5*Pi; rad += 0.1f) {
F result = SK_OPTS_NS::cos_(rad);
F expected = sk_float_cos(rad);
F delta = SK_OPTS_NS::abs_(expected - result);
REPORTER_ASSERT(r, SK_OPTS_NS::all(delta < kTolerance));
}
}
DEF_TEST(SkRasterPipelineOpts_Tan, r) {
using F = SK_OPTS_NS::F;
// Our tangent diverges more as we get near infinities (x near +- Pi/2),
// so we bring in the domain a little.
constexpr float Pi = SK_ScalarPI;
constexpr float kEpsilon = 0.16f;
constexpr float kTolerance = 0.00175f;
// Test against various multiples of Pi, to check our periodicity
for (float period : {0.0f, -3*Pi, 3*Pi}) {
for (float rad = -Pi/2 + kEpsilon; rad <= Pi/2 - kEpsilon; rad += 0.01f) {
F result = SK_OPTS_NS::tan_(rad + period);
F expected = sk_float_tan(rad);
F delta = SK_OPTS_NS::abs_(expected - result);
REPORTER_ASSERT(r, SK_OPTS_NS::all(delta < kTolerance));
}
}
}
DEF_TEST(SkRasterPipelineOpts_Atan, r) {
using F = SK_OPTS_NS::F;
constexpr float kTolerance = 0.00175f;
for (float x = -10.0f; x <= 10.0f; x += 0.1f) {
F result = SK_OPTS_NS::atan_(x);
F expected = atanf(x);
F delta = SK_OPTS_NS::abs_(expected - result);
REPORTER_ASSERT(r, SK_OPTS_NS::all(delta < kTolerance));
}
}