1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2011 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkPoint.h" 9cb93a386Sopenharmony_ci#include "include/private/SkColorData.h" 10cb93a386Sopenharmony_ci#include "include/private/SkFixed.h" 11cb93a386Sopenharmony_ci#include "include/private/SkHalf.h" 12cb93a386Sopenharmony_ci#include "include/private/SkTPin.h" 13cb93a386Sopenharmony_ci#include "include/private/SkTo.h" 14cb93a386Sopenharmony_ci#include "include/utils/SkRandom.h" 15cb93a386Sopenharmony_ci#include "src/core/SkEndian.h" 16cb93a386Sopenharmony_ci#include "src/core/SkFDot6.h" 17cb93a386Sopenharmony_ci#include "src/core/SkMathPriv.h" 18cb93a386Sopenharmony_ci#include "tests/Test.h" 19cb93a386Sopenharmony_ci 20cb93a386Sopenharmony_ci#include <algorithm> 21cb93a386Sopenharmony_ci#include <cinttypes> 22cb93a386Sopenharmony_ci 23cb93a386Sopenharmony_cistatic void test_clz(skiatest::Reporter* reporter) { 24cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 32 == SkCLZ(0)); 25cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 31 == SkCLZ(1)); 26cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 1 == SkCLZ(1 << 30)); 27cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 1 == SkCLZ((1 << 30) | (1 << 24) | 1)); 28cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 0 == SkCLZ(~0U)); 29cb93a386Sopenharmony_ci 30cb93a386Sopenharmony_ci SkRandom rand; 31cb93a386Sopenharmony_ci for (int i = 0; i < 1000; ++i) { 32cb93a386Sopenharmony_ci uint32_t mask = rand.nextU(); 33cb93a386Sopenharmony_ci // need to get some zeros for testing, but in some obscure way so the 34cb93a386Sopenharmony_ci // compiler won't "see" that, and work-around calling the functions. 35cb93a386Sopenharmony_ci mask >>= (mask & 31); 36cb93a386Sopenharmony_ci int intri = SkCLZ(mask); 37cb93a386Sopenharmony_ci int porta = SkCLZ_portable(mask); 38cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, intri == porta, "mask:%d intri:%d porta:%d", mask, intri, porta); 39cb93a386Sopenharmony_ci } 40cb93a386Sopenharmony_ci} 41cb93a386Sopenharmony_ci 42cb93a386Sopenharmony_cistatic void test_ctz(skiatest::Reporter* reporter) { 43cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 32 == SkCTZ(0)); 44cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 0 == SkCTZ(1)); 45cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 30 == SkCTZ(1 << 30)); 46cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 2 == SkCTZ((1 << 30) | (1 << 24) | (1 << 2))); 47cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 0 == SkCTZ(~0U)); 48cb93a386Sopenharmony_ci 49cb93a386Sopenharmony_ci SkRandom rand; 50cb93a386Sopenharmony_ci for (int i = 0; i < 1000; ++i) { 51cb93a386Sopenharmony_ci uint32_t mask = rand.nextU(); 52cb93a386Sopenharmony_ci // need to get some zeros for testing, but in some obscure way so the 53cb93a386Sopenharmony_ci // compiler won't "see" that, and work-around calling the functions. 54cb93a386Sopenharmony_ci mask >>= (mask & 31); 55cb93a386Sopenharmony_ci int intri = SkCTZ(mask); 56cb93a386Sopenharmony_ci int porta = SkCTZ_portable(mask); 57cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, intri == porta, "mask:%d intri:%d porta:%d", mask, intri, porta); 58cb93a386Sopenharmony_ci } 59cb93a386Sopenharmony_ci} 60cb93a386Sopenharmony_ci 61cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 62cb93a386Sopenharmony_ci 63cb93a386Sopenharmony_cistatic float sk_fsel(float pred, float result_ge, float result_lt) { 64cb93a386Sopenharmony_ci return pred >= 0 ? result_ge : result_lt; 65cb93a386Sopenharmony_ci} 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_cistatic float fast_floor(float x) { 68cb93a386Sopenharmony_ci// float big = sk_fsel(x, 0x1.0p+23, -0x1.0p+23); 69cb93a386Sopenharmony_ci float big = sk_fsel(x, (float)(1 << 23), -(float)(1 << 23)); 70cb93a386Sopenharmony_ci return (float)(x + big) - big; 71cb93a386Sopenharmony_ci} 72cb93a386Sopenharmony_ci 73cb93a386Sopenharmony_cistatic float std_floor(float x) { 74cb93a386Sopenharmony_ci return sk_float_floor(x); 75cb93a386Sopenharmony_ci} 76cb93a386Sopenharmony_ci 77cb93a386Sopenharmony_cistatic void test_floor_value(skiatest::Reporter* reporter, float value) { 78cb93a386Sopenharmony_ci float fast = fast_floor(value); 79cb93a386Sopenharmony_ci float std = std_floor(value); 80cb93a386Sopenharmony_ci if (std != fast) { 81cb93a386Sopenharmony_ci ERRORF(reporter, "fast_floor(%.9g) == %.9g != %.9g == std_floor(%.9g)", 82cb93a386Sopenharmony_ci value, fast, std, value); 83cb93a386Sopenharmony_ci } 84cb93a386Sopenharmony_ci} 85cb93a386Sopenharmony_ci 86cb93a386Sopenharmony_cistatic void test_floor(skiatest::Reporter* reporter) { 87cb93a386Sopenharmony_ci static const float gVals[] = { 88cb93a386Sopenharmony_ci 0, 1, 1.1f, 1.01f, 1.001f, 1.0001f, 1.00001f, 1.000001f, 1.0000001f 89cb93a386Sopenharmony_ci }; 90cb93a386Sopenharmony_ci 91cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(gVals); ++i) { 92cb93a386Sopenharmony_ci test_floor_value(reporter, gVals[i]); 93cb93a386Sopenharmony_ci// test_floor_value(reporter, -gVals[i]); 94cb93a386Sopenharmony_ci } 95cb93a386Sopenharmony_ci} 96cb93a386Sopenharmony_ci 97cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 98cb93a386Sopenharmony_ci 99cb93a386Sopenharmony_cistatic float float_blend(int src, int dst, float unit) { 100cb93a386Sopenharmony_ci return dst + (src - dst) * unit; 101cb93a386Sopenharmony_ci} 102cb93a386Sopenharmony_ci 103cb93a386Sopenharmony_cistatic int blend31(int src, int dst, int a31) { 104cb93a386Sopenharmony_ci return dst + ((src - dst) * a31 * 2114 >> 16); 105cb93a386Sopenharmony_ci // return dst + ((src - dst) * a31 * 33 >> 10); 106cb93a386Sopenharmony_ci} 107cb93a386Sopenharmony_ci 108cb93a386Sopenharmony_cistatic int blend31_slow(int src, int dst, int a31) { 109cb93a386Sopenharmony_ci int prod = src * a31 + (31 - a31) * dst + 16; 110cb93a386Sopenharmony_ci prod = (prod + (prod >> 5)) >> 5; 111cb93a386Sopenharmony_ci return prod; 112cb93a386Sopenharmony_ci} 113cb93a386Sopenharmony_ci 114cb93a386Sopenharmony_cistatic int blend31_round(int src, int dst, int a31) { 115cb93a386Sopenharmony_ci int prod = (src - dst) * a31 + 16; 116cb93a386Sopenharmony_ci prod = (prod + (prod >> 5)) >> 5; 117cb93a386Sopenharmony_ci return dst + prod; 118cb93a386Sopenharmony_ci} 119cb93a386Sopenharmony_ci 120cb93a386Sopenharmony_cistatic int blend31_old(int src, int dst, int a31) { 121cb93a386Sopenharmony_ci a31 += a31 >> 4; 122cb93a386Sopenharmony_ci return dst + ((src - dst) * a31 >> 5); 123cb93a386Sopenharmony_ci} 124cb93a386Sopenharmony_ci 125cb93a386Sopenharmony_ci// suppress unused code warning 126cb93a386Sopenharmony_cistatic int (*blend_functions[])(int, int, int) = { 127cb93a386Sopenharmony_ci blend31, 128cb93a386Sopenharmony_ci blend31_slow, 129cb93a386Sopenharmony_ci blend31_round, 130cb93a386Sopenharmony_ci blend31_old 131cb93a386Sopenharmony_ci}; 132cb93a386Sopenharmony_ci 133cb93a386Sopenharmony_cistatic void test_blend31() { 134cb93a386Sopenharmony_ci int failed = 0; 135cb93a386Sopenharmony_ci int death = 0; 136cb93a386Sopenharmony_ci if (false) { // avoid bit rot, suppress warning 137cb93a386Sopenharmony_ci failed = (*blend_functions[0])(0,0,0); 138cb93a386Sopenharmony_ci } 139cb93a386Sopenharmony_ci for (int src = 0; src <= 255; src++) { 140cb93a386Sopenharmony_ci for (int dst = 0; dst <= 255; dst++) { 141cb93a386Sopenharmony_ci for (int a = 0; a <= 31; a++) { 142cb93a386Sopenharmony_ci// int r0 = blend31(src, dst, a); 143cb93a386Sopenharmony_ci// int r0 = blend31_round(src, dst, a); 144cb93a386Sopenharmony_ci// int r0 = blend31_old(src, dst, a); 145cb93a386Sopenharmony_ci int r0 = blend31_slow(src, dst, a); 146cb93a386Sopenharmony_ci 147cb93a386Sopenharmony_ci float f = float_blend(src, dst, a / 31.f); 148cb93a386Sopenharmony_ci int r1 = (int)f; 149cb93a386Sopenharmony_ci int r2 = SkScalarRoundToInt(f); 150cb93a386Sopenharmony_ci 151cb93a386Sopenharmony_ci if (r0 != r1 && r0 != r2) { 152cb93a386Sopenharmony_ci SkDebugf("src:%d dst:%d a:%d result:%d float:%g\n", 153cb93a386Sopenharmony_ci src, dst, a, r0, f); 154cb93a386Sopenharmony_ci failed += 1; 155cb93a386Sopenharmony_ci } 156cb93a386Sopenharmony_ci if (r0 > 255) { 157cb93a386Sopenharmony_ci death += 1; 158cb93a386Sopenharmony_ci SkDebugf("death src:%d dst:%d a:%d result:%d float:%g\n", 159cb93a386Sopenharmony_ci src, dst, a, r0, f); 160cb93a386Sopenharmony_ci } 161cb93a386Sopenharmony_ci } 162cb93a386Sopenharmony_ci } 163cb93a386Sopenharmony_ci } 164cb93a386Sopenharmony_ci SkDebugf("---- failed %d death %d\n", failed, death); 165cb93a386Sopenharmony_ci} 166cb93a386Sopenharmony_ci 167cb93a386Sopenharmony_cistatic void check_length(skiatest::Reporter* reporter, 168cb93a386Sopenharmony_ci const SkPoint& p, SkScalar targetLen) { 169cb93a386Sopenharmony_ci float x = SkScalarToFloat(p.fX); 170cb93a386Sopenharmony_ci float y = SkScalarToFloat(p.fY); 171cb93a386Sopenharmony_ci float len = sk_float_sqrt(x*x + y*y); 172cb93a386Sopenharmony_ci 173cb93a386Sopenharmony_ci len /= SkScalarToFloat(targetLen); 174cb93a386Sopenharmony_ci 175cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, len > 0.999f && len < 1.001f); 176cb93a386Sopenharmony_ci} 177cb93a386Sopenharmony_ci 178cb93a386Sopenharmony_cistatic void unittest_isfinite(skiatest::Reporter* reporter) { 179cb93a386Sopenharmony_ci float nan = sk_float_asin(2); 180cb93a386Sopenharmony_ci float inf = SK_ScalarInfinity; 181cb93a386Sopenharmony_ci float big = 3.40282e+038f; 182cb93a386Sopenharmony_ci 183cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkScalarIsNaN(inf)); 184cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkScalarIsNaN(-inf)); 185cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkScalarIsFinite(inf)); 186cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkScalarIsFinite(-inf)); 187cb93a386Sopenharmony_ci 188cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkScalarIsNaN(nan)); 189cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkScalarIsNaN(big)); 190cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkScalarIsNaN(-big)); 191cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkScalarIsNaN(0)); 192cb93a386Sopenharmony_ci 193cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkScalarIsFinite(nan)); 194cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkScalarIsFinite(big)); 195cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkScalarIsFinite(-big)); 196cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkScalarIsFinite(0)); 197cb93a386Sopenharmony_ci} 198cb93a386Sopenharmony_ci 199cb93a386Sopenharmony_cistatic void unittest_half(skiatest::Reporter* reporter) { 200cb93a386Sopenharmony_ci static const float gFloats[] = { 201cb93a386Sopenharmony_ci 0.f, 1.f, 0.5f, 0.499999f, 0.5000001f, 1.f/3, 202cb93a386Sopenharmony_ci -0.f, -1.f, -0.5f, -0.499999f, -0.5000001f, -1.f/3 203cb93a386Sopenharmony_ci }; 204cb93a386Sopenharmony_ci 205cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(gFloats); ++i) { 206cb93a386Sopenharmony_ci SkHalf h = SkFloatToHalf(gFloats[i]); 207cb93a386Sopenharmony_ci float f = SkHalfToFloat(h); 208cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkScalarNearlyEqual(f, gFloats[i])); 209cb93a386Sopenharmony_ci } 210cb93a386Sopenharmony_ci 211cb93a386Sopenharmony_ci // check some special values 212cb93a386Sopenharmony_ci union FloatUnion { 213cb93a386Sopenharmony_ci uint32_t fU; 214cb93a386Sopenharmony_ci float fF; 215cb93a386Sopenharmony_ci }; 216cb93a386Sopenharmony_ci 217cb93a386Sopenharmony_ci static const FloatUnion largestPositiveHalf = { ((142 << 23) | (1023 << 13)) }; 218cb93a386Sopenharmony_ci SkHalf h = SkFloatToHalf(largestPositiveHalf.fF); 219cb93a386Sopenharmony_ci float f = SkHalfToFloat(h); 220cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkScalarNearlyEqual(f, largestPositiveHalf.fF)); 221cb93a386Sopenharmony_ci 222cb93a386Sopenharmony_ci static const FloatUnion largestNegativeHalf = { (1u << 31) | (142u << 23) | (1023u << 13) }; 223cb93a386Sopenharmony_ci h = SkFloatToHalf(largestNegativeHalf.fF); 224cb93a386Sopenharmony_ci f = SkHalfToFloat(h); 225cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkScalarNearlyEqual(f, largestNegativeHalf.fF)); 226cb93a386Sopenharmony_ci 227cb93a386Sopenharmony_ci static const FloatUnion smallestPositiveHalf = { 102 << 23 }; 228cb93a386Sopenharmony_ci h = SkFloatToHalf(smallestPositiveHalf.fF); 229cb93a386Sopenharmony_ci f = SkHalfToFloat(h); 230cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkScalarNearlyEqual(f, smallestPositiveHalf.fF)); 231cb93a386Sopenharmony_ci 232cb93a386Sopenharmony_ci static const FloatUnion overflowHalf = { ((143 << 23) | (1023 << 13)) }; 233cb93a386Sopenharmony_ci h = SkFloatToHalf(overflowHalf.fF); 234cb93a386Sopenharmony_ci f = SkHalfToFloat(h); 235cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkScalarIsFinite(f) ); 236cb93a386Sopenharmony_ci 237cb93a386Sopenharmony_ci static const FloatUnion underflowHalf = { 101 << 23 }; 238cb93a386Sopenharmony_ci h = SkFloatToHalf(underflowHalf.fF); 239cb93a386Sopenharmony_ci f = SkHalfToFloat(h); 240cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, f == 0.0f ); 241cb93a386Sopenharmony_ci 242cb93a386Sopenharmony_ci static const FloatUnion inf32 = { 255 << 23 }; 243cb93a386Sopenharmony_ci h = SkFloatToHalf(inf32.fF); 244cb93a386Sopenharmony_ci f = SkHalfToFloat(h); 245cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkScalarIsFinite(f) ); 246cb93a386Sopenharmony_ci 247cb93a386Sopenharmony_ci static const FloatUnion nan32 = { 255 << 23 | 1 }; 248cb93a386Sopenharmony_ci h = SkFloatToHalf(nan32.fF); 249cb93a386Sopenharmony_ci f = SkHalfToFloat(h); 250cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkScalarIsNaN(f) ); 251cb93a386Sopenharmony_ci 252cb93a386Sopenharmony_ci} 253cb93a386Sopenharmony_ci 254cb93a386Sopenharmony_citemplate <typename RSqrtFn> 255cb93a386Sopenharmony_cistatic void test_rsqrt(skiatest::Reporter* reporter, RSqrtFn rsqrt) { 256cb93a386Sopenharmony_ci const float maxRelativeError = 6.50196699e-4f; 257cb93a386Sopenharmony_ci 258cb93a386Sopenharmony_ci // test close to 0 up to 1 259cb93a386Sopenharmony_ci float input = 0.000001f; 260cb93a386Sopenharmony_ci for (int i = 0; i < 1000; ++i) { 261cb93a386Sopenharmony_ci float exact = 1.0f/sk_float_sqrt(input); 262cb93a386Sopenharmony_ci float estimate = rsqrt(input); 263cb93a386Sopenharmony_ci float relativeError = sk_float_abs(exact - estimate)/exact; 264cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, relativeError <= maxRelativeError); 265cb93a386Sopenharmony_ci input += 0.001f; 266cb93a386Sopenharmony_ci } 267cb93a386Sopenharmony_ci 268cb93a386Sopenharmony_ci // test 1 to ~100 269cb93a386Sopenharmony_ci input = 1.0f; 270cb93a386Sopenharmony_ci for (int i = 0; i < 1000; ++i) { 271cb93a386Sopenharmony_ci float exact = 1.0f/sk_float_sqrt(input); 272cb93a386Sopenharmony_ci float estimate = rsqrt(input); 273cb93a386Sopenharmony_ci float relativeError = sk_float_abs(exact - estimate)/exact; 274cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, relativeError <= maxRelativeError); 275cb93a386Sopenharmony_ci input += 0.01f; 276cb93a386Sopenharmony_ci } 277cb93a386Sopenharmony_ci 278cb93a386Sopenharmony_ci // test some big numbers 279cb93a386Sopenharmony_ci input = 1000000.0f; 280cb93a386Sopenharmony_ci for (int i = 0; i < 100; ++i) { 281cb93a386Sopenharmony_ci float exact = 1.0f/sk_float_sqrt(input); 282cb93a386Sopenharmony_ci float estimate = rsqrt(input); 283cb93a386Sopenharmony_ci float relativeError = sk_float_abs(exact - estimate)/exact; 284cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, relativeError <= maxRelativeError); 285cb93a386Sopenharmony_ci input += 754326.f; 286cb93a386Sopenharmony_ci } 287cb93a386Sopenharmony_ci} 288cb93a386Sopenharmony_ci 289cb93a386Sopenharmony_cistatic void test_nextlog2(skiatest::Reporter* r) { 290cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(-std::numeric_limits<float>::infinity()) == 0); 291cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(-std::numeric_limits<float>::max()) == 0); 292cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(-1000.0f) == 0); 293cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(-0.1f) == 0); 294cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(-std::numeric_limits<float>::min()) == 0); 295cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(-std::numeric_limits<float>::denorm_min()) == 0); 296cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(0.0f) == 0); 297cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(std::numeric_limits<float>::denorm_min()) == 0); 298cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(std::numeric_limits<float>::min()) == 0); 299cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(0.1f) == 0); 300cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(1.0f) == 0); 301cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(1.1f) == 1); 302cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(2.0f) == 1); 303cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(2.1f) == 2); 304cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(3.0f) == 2); 305cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(3.1f) == 2); 306cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(4.0f) == 2); 307cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(4.1f) == 3); 308cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(5.0f) == 3); 309cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(5.1f) == 3); 310cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(6.0f) == 3); 311cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(6.1f) == 3); 312cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(7.0f) == 3); 313cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(7.1f) == 3); 314cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(8.0f) == 3); 315cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(8.1f) == 4); 316cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(9.0f) == 4); 317cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(9.1f) == 4); 318cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(std::numeric_limits<float>::max()) == 128); 319cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(std::numeric_limits<float>::infinity()) > 0); 320cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(std::numeric_limits<float>::quiet_NaN()) >= 0); 321cb93a386Sopenharmony_ci 322cb93a386Sopenharmony_ci for (int i = 0; i < 100; ++i) { 323cb93a386Sopenharmony_ci float pow2 = std::ldexp(1, i); 324cb93a386Sopenharmony_ci float epsilon = std::ldexp(SK_ScalarNearlyZero, i); 325cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(pow2) == i); 326cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(pow2 + epsilon) == i + 1); 327cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_float_nextlog2(pow2 - epsilon) == i); 328cb93a386Sopenharmony_ci } 329cb93a386Sopenharmony_ci} 330cb93a386Sopenharmony_ci 331cb93a386Sopenharmony_cistatic void test_muldiv255(skiatest::Reporter* reporter) { 332cb93a386Sopenharmony_ci for (int a = 0; a <= 255; a++) { 333cb93a386Sopenharmony_ci for (int b = 0; b <= 255; b++) { 334cb93a386Sopenharmony_ci int ab = a * b; 335cb93a386Sopenharmony_ci float s = ab / 255.0f; 336cb93a386Sopenharmony_ci int round = (int)floorf(s + 0.5f); 337cb93a386Sopenharmony_ci int trunc = (int)floorf(s); 338cb93a386Sopenharmony_ci 339cb93a386Sopenharmony_ci int iround = SkMulDiv255Round(a, b); 340cb93a386Sopenharmony_ci int itrunc = SkMulDiv255Trunc(a, b); 341cb93a386Sopenharmony_ci 342cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, iround == round); 343cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, itrunc == trunc); 344cb93a386Sopenharmony_ci 345cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, itrunc <= iround); 346cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, iround <= a); 347cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, iround <= b); 348cb93a386Sopenharmony_ci } 349cb93a386Sopenharmony_ci } 350cb93a386Sopenharmony_ci} 351cb93a386Sopenharmony_ci 352cb93a386Sopenharmony_cistatic void test_muldiv255ceiling(skiatest::Reporter* reporter) { 353cb93a386Sopenharmony_ci for (int c = 0; c <= 255; c++) { 354cb93a386Sopenharmony_ci for (int a = 0; a <= 255; a++) { 355cb93a386Sopenharmony_ci int product = (c * a + 255); 356cb93a386Sopenharmony_ci int expected_ceiling = (product + (product >> 8)) >> 8; 357cb93a386Sopenharmony_ci int webkit_ceiling = (c * a + 254) / 255; 358cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, expected_ceiling == webkit_ceiling); 359cb93a386Sopenharmony_ci int skia_ceiling = SkMulDiv255Ceiling(c, a); 360cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, skia_ceiling == webkit_ceiling); 361cb93a386Sopenharmony_ci } 362cb93a386Sopenharmony_ci } 363cb93a386Sopenharmony_ci} 364cb93a386Sopenharmony_ci 365cb93a386Sopenharmony_cistatic void test_copysign(skiatest::Reporter* reporter) { 366cb93a386Sopenharmony_ci static const int32_t gTriples[] = { 367cb93a386Sopenharmony_ci // x, y, expected result 368cb93a386Sopenharmony_ci 0, 0, 0, 369cb93a386Sopenharmony_ci 0, 1, 0, 370cb93a386Sopenharmony_ci 0, -1, 0, 371cb93a386Sopenharmony_ci 1, 0, 1, 372cb93a386Sopenharmony_ci 1, 1, 1, 373cb93a386Sopenharmony_ci 1, -1, -1, 374cb93a386Sopenharmony_ci -1, 0, 1, 375cb93a386Sopenharmony_ci -1, 1, 1, 376cb93a386Sopenharmony_ci -1, -1, -1, 377cb93a386Sopenharmony_ci }; 378cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(gTriples); i += 3) { 379cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 380cb93a386Sopenharmony_ci SkCopySign32(gTriples[i], gTriples[i+1]) == gTriples[i+2]); 381cb93a386Sopenharmony_ci float x = (float)gTriples[i]; 382cb93a386Sopenharmony_ci float y = (float)gTriples[i+1]; 383cb93a386Sopenharmony_ci float expected = (float)gTriples[i+2]; 384cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, sk_float_copysign(x, y) == expected); 385cb93a386Sopenharmony_ci } 386cb93a386Sopenharmony_ci 387cb93a386Sopenharmony_ci SkRandom rand; 388cb93a386Sopenharmony_ci for (int j = 0; j < 1000; j++) { 389cb93a386Sopenharmony_ci int ix = rand.nextS(); 390cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkCopySign32(ix, ix) == ix); 391cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkCopySign32(ix, -ix) == -ix); 392cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkCopySign32(-ix, ix) == ix); 393cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkCopySign32(-ix, -ix) == -ix); 394cb93a386Sopenharmony_ci 395cb93a386Sopenharmony_ci SkScalar sx = rand.nextSScalar1(); 396cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkScalarCopySign(sx, sx) == sx); 397cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkScalarCopySign(sx, -sx) == -sx); 398cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkScalarCopySign(-sx, sx) == sx); 399cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkScalarCopySign(-sx, -sx) == -sx); 400cb93a386Sopenharmony_ci } 401cb93a386Sopenharmony_ci} 402cb93a386Sopenharmony_ci 403cb93a386Sopenharmony_cistatic void huge_vector_normalize(skiatest::Reporter* reporter) { 404cb93a386Sopenharmony_ci // these values should fail (overflow/underflow) trying to normalize 405cb93a386Sopenharmony_ci const SkVector fail[] = { 406cb93a386Sopenharmony_ci { 0, 0 }, 407cb93a386Sopenharmony_ci { SK_ScalarInfinity, 0 }, { 0, SK_ScalarInfinity }, 408cb93a386Sopenharmony_ci { 0, SK_ScalarNaN }, { SK_ScalarNaN, 0 }, 409cb93a386Sopenharmony_ci }; 410cb93a386Sopenharmony_ci for (SkVector v : fail) { 411cb93a386Sopenharmony_ci SkVector v2 = v; 412cb93a386Sopenharmony_ci if (v2.setLength(1.0f)) { 413cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !v.setLength(1.0f)); 414cb93a386Sopenharmony_ci } 415cb93a386Sopenharmony_ci } 416cb93a386Sopenharmony_ci} 417cb93a386Sopenharmony_ci 418cb93a386Sopenharmony_ciDEF_TEST(Math, reporter) { 419cb93a386Sopenharmony_ci int i; 420cb93a386Sopenharmony_ci SkRandom rand; 421cb93a386Sopenharmony_ci 422cb93a386Sopenharmony_ci // these should assert 423cb93a386Sopenharmony_ci#if 0 424cb93a386Sopenharmony_ci SkToS8(128); 425cb93a386Sopenharmony_ci SkToS8(-129); 426cb93a386Sopenharmony_ci SkToU8(256); 427cb93a386Sopenharmony_ci SkToU8(-5); 428cb93a386Sopenharmony_ci 429cb93a386Sopenharmony_ci SkToS16(32768); 430cb93a386Sopenharmony_ci SkToS16(-32769); 431cb93a386Sopenharmony_ci SkToU16(65536); 432cb93a386Sopenharmony_ci SkToU16(-5); 433cb93a386Sopenharmony_ci 434cb93a386Sopenharmony_ci if (sizeof(size_t) > 4) { 435cb93a386Sopenharmony_ci SkToS32(4*1024*1024); 436cb93a386Sopenharmony_ci SkToS32(-4*1024*1024); 437cb93a386Sopenharmony_ci SkToU32(5*1024*1024); 438cb93a386Sopenharmony_ci SkToU32(-5); 439cb93a386Sopenharmony_ci } 440cb93a386Sopenharmony_ci#endif 441cb93a386Sopenharmony_ci 442cb93a386Sopenharmony_ci test_muldiv255(reporter); 443cb93a386Sopenharmony_ci test_muldiv255ceiling(reporter); 444cb93a386Sopenharmony_ci test_copysign(reporter); 445cb93a386Sopenharmony_ci 446cb93a386Sopenharmony_ci { 447cb93a386Sopenharmony_ci SkScalar x = SK_ScalarNaN; 448cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkScalarIsNaN(x)); 449cb93a386Sopenharmony_ci } 450cb93a386Sopenharmony_ci 451cb93a386Sopenharmony_ci for (i = 0; i < 10000; i++) { 452cb93a386Sopenharmony_ci SkPoint p; 453cb93a386Sopenharmony_ci 454cb93a386Sopenharmony_ci // These random values are being treated as 32-bit-patterns, not as 455cb93a386Sopenharmony_ci // ints; calling SkIntToScalar() here produces crashes. 456cb93a386Sopenharmony_ci p.setLength((SkScalar) rand.nextS(), 457cb93a386Sopenharmony_ci (SkScalar) rand.nextS(), 458cb93a386Sopenharmony_ci SK_Scalar1); 459cb93a386Sopenharmony_ci check_length(reporter, p, SK_Scalar1); 460cb93a386Sopenharmony_ci p.setLength((SkScalar) (rand.nextS() >> 13), 461cb93a386Sopenharmony_ci (SkScalar) (rand.nextS() >> 13), 462cb93a386Sopenharmony_ci SK_Scalar1); 463cb93a386Sopenharmony_ci check_length(reporter, p, SK_Scalar1); 464cb93a386Sopenharmony_ci } 465cb93a386Sopenharmony_ci 466cb93a386Sopenharmony_ci { 467cb93a386Sopenharmony_ci SkFixed result = SkFixedDiv(100, 100); 468cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, result == SK_Fixed1); 469cb93a386Sopenharmony_ci result = SkFixedDiv(1, SK_Fixed1); 470cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, result == 1); 471cb93a386Sopenharmony_ci result = SkFixedDiv(10 - 1, SK_Fixed1 * 3); 472cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, result == 3); 473cb93a386Sopenharmony_ci } 474cb93a386Sopenharmony_ci 475cb93a386Sopenharmony_ci { 476cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, (SkFixedRoundToFixed(-SK_Fixed1 * 10) >> 1) == -SK_Fixed1 * 5); 477cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, (SkFixedFloorToFixed(-SK_Fixed1 * 10) >> 1) == -SK_Fixed1 * 5); 478cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, (SkFixedCeilToFixed(-SK_Fixed1 * 10) >> 1) == -SK_Fixed1 * 5); 479cb93a386Sopenharmony_ci } 480cb93a386Sopenharmony_ci 481cb93a386Sopenharmony_ci huge_vector_normalize(reporter); 482cb93a386Sopenharmony_ci unittest_isfinite(reporter); 483cb93a386Sopenharmony_ci unittest_half(reporter); 484cb93a386Sopenharmony_ci test_rsqrt(reporter, sk_float_rsqrt); 485cb93a386Sopenharmony_ci test_rsqrt(reporter, sk_float_rsqrt_portable); 486cb93a386Sopenharmony_ci test_nextlog2(reporter); 487cb93a386Sopenharmony_ci 488cb93a386Sopenharmony_ci for (i = 0; i < 10000; i++) { 489cb93a386Sopenharmony_ci SkFixed numer = rand.nextS(); 490cb93a386Sopenharmony_ci SkFixed denom = rand.nextS(); 491cb93a386Sopenharmony_ci SkFixed result = SkFixedDiv(numer, denom); 492cb93a386Sopenharmony_ci int64_t check = SkLeftShift((int64_t)numer, 16) / denom; 493cb93a386Sopenharmony_ci 494cb93a386Sopenharmony_ci (void)SkCLZ(numer); 495cb93a386Sopenharmony_ci (void)SkCLZ(denom); 496cb93a386Sopenharmony_ci 497cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, result != (SkFixed)SK_NaN32); 498cb93a386Sopenharmony_ci if (check > SK_MaxS32) { 499cb93a386Sopenharmony_ci check = SK_MaxS32; 500cb93a386Sopenharmony_ci } else if (check < -SK_MaxS32) { 501cb93a386Sopenharmony_ci check = SK_MinS32; 502cb93a386Sopenharmony_ci } 503cb93a386Sopenharmony_ci if (result != (int32_t)check) { 504cb93a386Sopenharmony_ci ERRORF(reporter, "\nFixed Divide: %8x / %8x -> %8x %8" PRIx64 "\n", numer, denom, 505cb93a386Sopenharmony_ci result, check); 506cb93a386Sopenharmony_ci } 507cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, result == (int32_t)check); 508cb93a386Sopenharmony_ci } 509cb93a386Sopenharmony_ci 510cb93a386Sopenharmony_ci if (false) test_floor(reporter); 511cb93a386Sopenharmony_ci 512cb93a386Sopenharmony_ci // disable for now 513cb93a386Sopenharmony_ci if (false) test_blend31(); // avoid bit rot, suppress warning 514cb93a386Sopenharmony_ci 515cb93a386Sopenharmony_ci test_clz(reporter); 516cb93a386Sopenharmony_ci test_ctz(reporter); 517cb93a386Sopenharmony_ci} 518cb93a386Sopenharmony_ci 519cb93a386Sopenharmony_citemplate <typename T> struct PairRec { 520cb93a386Sopenharmony_ci T fYin; 521cb93a386Sopenharmony_ci T fYang; 522cb93a386Sopenharmony_ci}; 523cb93a386Sopenharmony_ci 524cb93a386Sopenharmony_ciDEF_TEST(TestEndian, reporter) { 525cb93a386Sopenharmony_ci static const PairRec<uint16_t> g16[] = { 526cb93a386Sopenharmony_ci { 0x0, 0x0 }, 527cb93a386Sopenharmony_ci { 0xFFFF, 0xFFFF }, 528cb93a386Sopenharmony_ci { 0x1122, 0x2211 }, 529cb93a386Sopenharmony_ci }; 530cb93a386Sopenharmony_ci static const PairRec<uint32_t> g32[] = { 531cb93a386Sopenharmony_ci { 0x0, 0x0 }, 532cb93a386Sopenharmony_ci { 0xFFFFFFFF, 0xFFFFFFFF }, 533cb93a386Sopenharmony_ci { 0x11223344, 0x44332211 }, 534cb93a386Sopenharmony_ci }; 535cb93a386Sopenharmony_ci static const PairRec<uint64_t> g64[] = { 536cb93a386Sopenharmony_ci { 0x0, 0x0 }, 537cb93a386Sopenharmony_ci { 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL }, 538cb93a386Sopenharmony_ci { 0x1122334455667788ULL, 0x8877665544332211ULL }, 539cb93a386Sopenharmony_ci }; 540cb93a386Sopenharmony_ci 541cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 0x1122 == SkTEndianSwap16<0x2211>::value); 542cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 0x11223344 == SkTEndianSwap32<0x44332211>::value); 543cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 0x1122334455667788ULL == SkTEndianSwap64<0x8877665544332211ULL>::value); 544cb93a386Sopenharmony_ci 545cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(g16); ++i) { 546cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, g16[i].fYang == SkEndianSwap16(g16[i].fYin)); 547cb93a386Sopenharmony_ci } 548cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(g32); ++i) { 549cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, g32[i].fYang == SkEndianSwap32(g32[i].fYin)); 550cb93a386Sopenharmony_ci } 551cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(g64); ++i) { 552cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, g64[i].fYang == SkEndianSwap64(g64[i].fYin)); 553cb93a386Sopenharmony_ci } 554cb93a386Sopenharmony_ci} 555cb93a386Sopenharmony_ci 556cb93a386Sopenharmony_citemplate <typename T> 557cb93a386Sopenharmony_cistatic void test_divmod(skiatest::Reporter* r) { 558cb93a386Sopenharmony_ci#if !defined(__MSVC_RUNTIME_CHECKS) 559cb93a386Sopenharmony_ci const struct { 560cb93a386Sopenharmony_ci T numer; 561cb93a386Sopenharmony_ci T denom; 562cb93a386Sopenharmony_ci } kEdgeCases[] = { 563cb93a386Sopenharmony_ci {(T)17, (T)17}, 564cb93a386Sopenharmony_ci {(T)17, (T)4}, 565cb93a386Sopenharmony_ci {(T)0, (T)17}, 566cb93a386Sopenharmony_ci // For unsigned T these negatives are just some large numbers. Doesn't hurt to test them. 567cb93a386Sopenharmony_ci {(T)-17, (T)-17}, 568cb93a386Sopenharmony_ci {(T)-17, (T)4}, 569cb93a386Sopenharmony_ci {(T)17, (T)-4}, 570cb93a386Sopenharmony_ci {(T)-17, (T)-4}, 571cb93a386Sopenharmony_ci }; 572cb93a386Sopenharmony_ci 573cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(kEdgeCases); i++) { 574cb93a386Sopenharmony_ci const T numer = kEdgeCases[i].numer; 575cb93a386Sopenharmony_ci const T denom = kEdgeCases[i].denom; 576cb93a386Sopenharmony_ci T div, mod; 577cb93a386Sopenharmony_ci SkTDivMod(numer, denom, &div, &mod); 578cb93a386Sopenharmony_ci REPORTER_ASSERT(r, numer/denom == div); 579cb93a386Sopenharmony_ci REPORTER_ASSERT(r, numer%denom == mod); 580cb93a386Sopenharmony_ci } 581cb93a386Sopenharmony_ci 582cb93a386Sopenharmony_ci SkRandom rand; 583cb93a386Sopenharmony_ci for (size_t i = 0; i < 10000; i++) { 584cb93a386Sopenharmony_ci const T numer = (T)rand.nextS(); 585cb93a386Sopenharmony_ci T denom = 0; 586cb93a386Sopenharmony_ci while (0 == denom) { 587cb93a386Sopenharmony_ci denom = (T)rand.nextS(); 588cb93a386Sopenharmony_ci } 589cb93a386Sopenharmony_ci T div, mod; 590cb93a386Sopenharmony_ci SkTDivMod(numer, denom, &div, &mod); 591cb93a386Sopenharmony_ci REPORTER_ASSERT(r, numer/denom == div); 592cb93a386Sopenharmony_ci REPORTER_ASSERT(r, numer%denom == mod); 593cb93a386Sopenharmony_ci } 594cb93a386Sopenharmony_ci#endif 595cb93a386Sopenharmony_ci} 596cb93a386Sopenharmony_ci 597cb93a386Sopenharmony_ciDEF_TEST(divmod_u8, r) { 598cb93a386Sopenharmony_ci test_divmod<uint8_t>(r); 599cb93a386Sopenharmony_ci} 600cb93a386Sopenharmony_ci 601cb93a386Sopenharmony_ciDEF_TEST(divmod_u16, r) { 602cb93a386Sopenharmony_ci test_divmod<uint16_t>(r); 603cb93a386Sopenharmony_ci} 604cb93a386Sopenharmony_ci 605cb93a386Sopenharmony_ciDEF_TEST(divmod_u32, r) { 606cb93a386Sopenharmony_ci test_divmod<uint32_t>(r); 607cb93a386Sopenharmony_ci} 608cb93a386Sopenharmony_ci 609cb93a386Sopenharmony_ciDEF_TEST(divmod_u64, r) { 610cb93a386Sopenharmony_ci test_divmod<uint64_t>(r); 611cb93a386Sopenharmony_ci} 612cb93a386Sopenharmony_ci 613cb93a386Sopenharmony_ciDEF_TEST(divmod_s8, r) { 614cb93a386Sopenharmony_ci test_divmod<int8_t>(r); 615cb93a386Sopenharmony_ci} 616cb93a386Sopenharmony_ci 617cb93a386Sopenharmony_ciDEF_TEST(divmod_s16, r) { 618cb93a386Sopenharmony_ci test_divmod<int16_t>(r); 619cb93a386Sopenharmony_ci} 620cb93a386Sopenharmony_ci 621cb93a386Sopenharmony_ciDEF_TEST(divmod_s32, r) { 622cb93a386Sopenharmony_ci test_divmod<int32_t>(r); 623cb93a386Sopenharmony_ci} 624cb93a386Sopenharmony_ci 625cb93a386Sopenharmony_ciDEF_TEST(divmod_s64, r) { 626cb93a386Sopenharmony_ci test_divmod<int64_t>(r); 627cb93a386Sopenharmony_ci} 628cb93a386Sopenharmony_ci 629cb93a386Sopenharmony_cistatic void test_nextsizepow2(skiatest::Reporter* r, size_t test, size_t expectedAns) { 630cb93a386Sopenharmony_ci size_t ans = GrNextSizePow2(test); 631cb93a386Sopenharmony_ci 632cb93a386Sopenharmony_ci REPORTER_ASSERT(r, ans == expectedAns); 633cb93a386Sopenharmony_ci //SkDebugf("0x%zx -> 0x%zx (0x%zx)\n", test, ans, expectedAns); 634cb93a386Sopenharmony_ci} 635cb93a386Sopenharmony_ci 636cb93a386Sopenharmony_ciDEF_TEST(GrNextSizePow2, reporter) { 637cb93a386Sopenharmony_ci constexpr int kNumSizeTBits = 8 * sizeof(size_t); 638cb93a386Sopenharmony_ci 639cb93a386Sopenharmony_ci size_t test = 0, expectedAns = 1; 640cb93a386Sopenharmony_ci 641cb93a386Sopenharmony_ci test_nextsizepow2(reporter, test, expectedAns); 642cb93a386Sopenharmony_ci 643cb93a386Sopenharmony_ci test = 1; expectedAns = 1; 644cb93a386Sopenharmony_ci 645cb93a386Sopenharmony_ci for (int i = 1; i < kNumSizeTBits; ++i) { 646cb93a386Sopenharmony_ci test_nextsizepow2(reporter, test, expectedAns); 647cb93a386Sopenharmony_ci 648cb93a386Sopenharmony_ci test++; 649cb93a386Sopenharmony_ci expectedAns <<= 1; 650cb93a386Sopenharmony_ci 651cb93a386Sopenharmony_ci test_nextsizepow2(reporter, test, expectedAns); 652cb93a386Sopenharmony_ci 653cb93a386Sopenharmony_ci test = expectedAns; 654cb93a386Sopenharmony_ci } 655cb93a386Sopenharmony_ci 656cb93a386Sopenharmony_ci // For the remaining three tests there is no higher power (of 2) 657cb93a386Sopenharmony_ci test = 0x1; 658cb93a386Sopenharmony_ci test <<= kNumSizeTBits-1; 659cb93a386Sopenharmony_ci test_nextsizepow2(reporter, test, test); 660cb93a386Sopenharmony_ci 661cb93a386Sopenharmony_ci test++; 662cb93a386Sopenharmony_ci test_nextsizepow2(reporter, test, test); 663cb93a386Sopenharmony_ci 664cb93a386Sopenharmony_ci test_nextsizepow2(reporter, SIZE_MAX, SIZE_MAX); 665cb93a386Sopenharmony_ci} 666cb93a386Sopenharmony_ci 667cb93a386Sopenharmony_ciDEF_TEST(FloatSaturate32, reporter) { 668cb93a386Sopenharmony_ci const struct { 669cb93a386Sopenharmony_ci float fFloat; 670cb93a386Sopenharmony_ci int fExpectedInt; 671cb93a386Sopenharmony_ci } recs[] = { 672cb93a386Sopenharmony_ci { 0, 0 }, 673cb93a386Sopenharmony_ci { 100.5f, 100 }, 674cb93a386Sopenharmony_ci { (float)SK_MaxS32, SK_MaxS32FitsInFloat }, 675cb93a386Sopenharmony_ci { (float)SK_MinS32, SK_MinS32FitsInFloat }, 676cb93a386Sopenharmony_ci { SK_MaxS32 * 100.0f, SK_MaxS32FitsInFloat }, 677cb93a386Sopenharmony_ci { SK_MinS32 * 100.0f, SK_MinS32FitsInFloat }, 678cb93a386Sopenharmony_ci { SK_ScalarInfinity, SK_MaxS32FitsInFloat }, 679cb93a386Sopenharmony_ci { SK_ScalarNegativeInfinity, SK_MinS32FitsInFloat }, 680cb93a386Sopenharmony_ci { SK_ScalarNaN, SK_MaxS32FitsInFloat }, 681cb93a386Sopenharmony_ci }; 682cb93a386Sopenharmony_ci 683cb93a386Sopenharmony_ci for (auto r : recs) { 684cb93a386Sopenharmony_ci int i = sk_float_saturate2int(r.fFloat); 685cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, r.fExpectedInt == i); 686cb93a386Sopenharmony_ci 687cb93a386Sopenharmony_ci // Ensure that SkTPin bounds even non-finite values (including NaN) 688cb93a386Sopenharmony_ci SkScalar p = SkTPin<SkScalar>(r.fFloat, 0, 100); 689cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p >= 0 && p <= 100); 690cb93a386Sopenharmony_ci } 691cb93a386Sopenharmony_ci} 692cb93a386Sopenharmony_ci 693cb93a386Sopenharmony_ciDEF_TEST(FloatSaturate64, reporter) { 694cb93a386Sopenharmony_ci const struct { 695cb93a386Sopenharmony_ci float fFloat; 696cb93a386Sopenharmony_ci int64_t fExpected64; 697cb93a386Sopenharmony_ci } recs[] = { 698cb93a386Sopenharmony_ci { 0, 0 }, 699cb93a386Sopenharmony_ci { 100.5f, 100 }, 700cb93a386Sopenharmony_ci { (float)SK_MaxS64, SK_MaxS64FitsInFloat }, 701cb93a386Sopenharmony_ci { (float)SK_MinS64, SK_MinS64FitsInFloat }, 702cb93a386Sopenharmony_ci { SK_MaxS64 * 100.0f, SK_MaxS64FitsInFloat }, 703cb93a386Sopenharmony_ci { SK_MinS64 * 100.0f, SK_MinS64FitsInFloat }, 704cb93a386Sopenharmony_ci { SK_ScalarInfinity, SK_MaxS64FitsInFloat }, 705cb93a386Sopenharmony_ci { SK_ScalarNegativeInfinity, SK_MinS64FitsInFloat }, 706cb93a386Sopenharmony_ci { SK_ScalarNaN, SK_MaxS64FitsInFloat }, 707cb93a386Sopenharmony_ci }; 708cb93a386Sopenharmony_ci 709cb93a386Sopenharmony_ci for (auto r : recs) { 710cb93a386Sopenharmony_ci int64_t i = sk_float_saturate2int64(r.fFloat); 711cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, r.fExpected64 == i); 712cb93a386Sopenharmony_ci } 713cb93a386Sopenharmony_ci} 714cb93a386Sopenharmony_ci 715cb93a386Sopenharmony_ciDEF_TEST(DoubleSaturate32, reporter) { 716cb93a386Sopenharmony_ci const struct { 717cb93a386Sopenharmony_ci double fDouble; 718cb93a386Sopenharmony_ci int fExpectedInt; 719cb93a386Sopenharmony_ci } recs[] = { 720cb93a386Sopenharmony_ci { 0, 0 }, 721cb93a386Sopenharmony_ci { 100.5, 100 }, 722cb93a386Sopenharmony_ci { SK_MaxS32, SK_MaxS32 }, 723cb93a386Sopenharmony_ci { SK_MinS32, SK_MinS32 }, 724cb93a386Sopenharmony_ci { SK_MaxS32 - 1, SK_MaxS32 - 1 }, 725cb93a386Sopenharmony_ci { SK_MinS32 + 1, SK_MinS32 + 1 }, 726cb93a386Sopenharmony_ci { SK_MaxS32 * 100.0, SK_MaxS32 }, 727cb93a386Sopenharmony_ci { SK_MinS32 * 100.0, SK_MinS32 }, 728cb93a386Sopenharmony_ci { SK_ScalarInfinity, SK_MaxS32 }, 729cb93a386Sopenharmony_ci { SK_ScalarNegativeInfinity, SK_MinS32 }, 730cb93a386Sopenharmony_ci { SK_ScalarNaN, SK_MaxS32 }, 731cb93a386Sopenharmony_ci }; 732cb93a386Sopenharmony_ci 733cb93a386Sopenharmony_ci for (auto r : recs) { 734cb93a386Sopenharmony_ci int i = sk_double_saturate2int(r.fDouble); 735cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, r.fExpectedInt == i); 736cb93a386Sopenharmony_ci } 737cb93a386Sopenharmony_ci} 738cb93a386Sopenharmony_ci 739cb93a386Sopenharmony_ci#if defined(__ARM_NEON) 740cb93a386Sopenharmony_ci #include <arm_neon.h> 741cb93a386Sopenharmony_ci 742cb93a386Sopenharmony_ci DEF_TEST(NeonU16Div255, r) { 743cb93a386Sopenharmony_ci 744cb93a386Sopenharmony_ci for (int v = 0; v <= 255*255; v++) { 745cb93a386Sopenharmony_ci int want = (v + 127)/255; 746cb93a386Sopenharmony_ci 747cb93a386Sopenharmony_ci uint16x8_t V = vdupq_n_u16(v); 748cb93a386Sopenharmony_ci int got = vrshrq_n_u16(vrsraq_n_u16(V, V, 8), 8)[0]; 749cb93a386Sopenharmony_ci 750cb93a386Sopenharmony_ci if (got != want) { 751cb93a386Sopenharmony_ci SkDebugf("%d -> %d, want %d\n", v, got, want); 752cb93a386Sopenharmony_ci } 753cb93a386Sopenharmony_ci REPORTER_ASSERT(r, got == want); 754cb93a386Sopenharmony_ci } 755cb93a386Sopenharmony_ci } 756cb93a386Sopenharmony_ci 757cb93a386Sopenharmony_ci#endif 758cb93a386Sopenharmony_ci 759cb93a386Sopenharmony_ciDEF_TEST(unit_floats, r) { 760cb93a386Sopenharmony_ci // pick a non-trivial, non-pow-2 value, to test the loop 761cb93a386Sopenharmony_ci float v[13]; 762cb93a386Sopenharmony_ci constexpr int N = SK_ARRAY_COUNT(v); 763cb93a386Sopenharmony_ci 764cb93a386Sopenharmony_ci // empty array reports true 765cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_floats_are_unit(v, 0)); 766cb93a386Sopenharmony_ci 767cb93a386Sopenharmony_ci SkRandom rand; 768cb93a386Sopenharmony_ci for (int outer = 0; outer < 1000; ++outer) { 769cb93a386Sopenharmony_ci // check some good values 770cb93a386Sopenharmony_ci for (int i = 0; i < N; ++i) { 771cb93a386Sopenharmony_ci v[i] = rand.nextUScalar1(); 772cb93a386Sopenharmony_ci } 773cb93a386Sopenharmony_ci const int index = rand.nextU() % N; 774cb93a386Sopenharmony_ci 775cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_floats_are_unit(v, N)); 776cb93a386Sopenharmony_ci v[index] = -0.f; 777cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_floats_are_unit(v, N)); 778cb93a386Sopenharmony_ci v[index] = 1.0f; 779cb93a386Sopenharmony_ci REPORTER_ASSERT(r, sk_floats_are_unit(v, N)); 780cb93a386Sopenharmony_ci 781cb93a386Sopenharmony_ci // check some bad values 782cb93a386Sopenharmony_ci const float non_norms[] = { 783cb93a386Sopenharmony_ci 1.0000001f, 2, SK_ScalarInfinity, SK_ScalarNaN 784cb93a386Sopenharmony_ci }; 785cb93a386Sopenharmony_ci for (float bad : non_norms) { 786cb93a386Sopenharmony_ci v[index] = bad; 787cb93a386Sopenharmony_ci REPORTER_ASSERT(r, !sk_floats_are_unit(v, N)); 788cb93a386Sopenharmony_ci v[index] = -bad; 789cb93a386Sopenharmony_ci REPORTER_ASSERT(r, !sk_floats_are_unit(v, N)); 790cb93a386Sopenharmony_ci } 791cb93a386Sopenharmony_ci } 792cb93a386Sopenharmony_ci} 793