chromium/third_party/skia/include/private/base/SkFloatingPoint.h

/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SkFloatingPoint_DEFINED
#define SkFloatingPoint_DEFINED

#include "include/private/base/SkAttributes.h"
#include "include/private/base/SkMath.h"

#include <cmath>
#include <cstdint>
#include <limits>
#include <type_traits>

inline constexpr float SK_FloatSqrt2 =;
inline constexpr float SK_FloatPI    =;
inline constexpr double SK_DoublePI  =;

static constexpr int sk_float_sgn(float x) {}

static constexpr float sk_float_degrees_to_radians(float degrees) {}

static constexpr float sk_float_radians_to_degrees(float radians) {}

// floor(double+0.5) vs. floorf(float+0.5f) give comparable performance, but upcasting to double
// means tricky values like 0.49999997 and 2^24 get rounded correctly. If these were rounded
// as floatf(x + .5f), they would be 1 higher than expected.
#define sk_float_round(x)

template <typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
static inline constexpr bool SkIsNaN(T x) {}

// Subtracting a value from itself will result in zero, except for NAN or ±Inf, which make NAN.
// Multiplying a group of values against zero will result in zero for each product, except for
// NAN or ±Inf, which will result in NAN and continue resulting in NAN for the rest of the elements.
// This generates better code than `std::isfinite` when building with clang-cl (April 2024).
template <typename T, typename... Pack, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
static inline bool SkIsFinite(T x, Pack... values) {}

template <typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
static inline bool SkIsFinite(const T array[], int count) {}

inline constexpr int SK_MaxS32FitsInFloat =;
inline constexpr int SK_MinS32FitsInFloat =;

// 0x7fffff8000000000
inline constexpr int64_t SK_MaxS64FitsInFloat =;
inline constexpr int64_t SK_MinS64FitsInFloat =;

// sk_[float|double]_saturate2int are written to return their maximum values when passed NaN.
// MSVC 19.38+ has a bug with this implementation, leading to incorrect results:
// https://developercommunity.visualstudio.com/t/Optimizer-incorrectly-handles-NaN-floati/10654403
//
// We inject an explicit NaN test on MSVC to work around the problem.
#if defined(_MSC_VER) && !defined(__clang__)
    #define SK_CHECK_NAN
#else
    #define SK_CHECK_NAN
#endif

/**
 *  Return the closest int for the given float. Returns SK_MaxS32FitsInFloat for NaN.
 */
static constexpr int sk_float_saturate2int(float x) {}

/**
 *  Return the closest int for the given double. Returns SK_MaxS32 for NaN.
 */
static constexpr int sk_double_saturate2int(double x) {}

/**
 *  Return the closest int64_t for the given float. Returns SK_MaxS64FitsInFloat for NaN.
 */
static constexpr int64_t sk_float_saturate2int64(float x) {}

#undef SK_CHECK_NAN

#define sk_float_floor2int(x)
#define sk_float_round2int(x)
#define sk_float_ceil2int(x)

#define sk_float_floor2int_no_saturate(x)
#define sk_float_round2int_no_saturate(x)
#define sk_float_ceil2int_no_saturate(x)

#define sk_double_round(x)
#define sk_double_floor2int(x)
#define sk_double_round2int(x)
#define sk_double_ceil2int(x)

// Cast double to float, ignoring any warning about too-large finite values being cast to float.
// Clang thinks this is undefined, but it's actually implementation defined to return either
// the largest float or infinity (one of the two bracketing representable floats).  Good enough!
SK_NO_SANITIZE("float-cast-overflow")
static constexpr float sk_double_to_float(double x) {}

inline constexpr float SK_FloatNaN =;
inline constexpr float SK_FloatInfinity =;
inline constexpr float SK_FloatNegativeInfinity =;

inline constexpr double SK_DoubleNaN =;

// Calculate the midpoint between a and b. Similar to std::midpoint in c++20.
static constexpr float sk_float_midpoint(float a, float b) {}

static inline float sk_float_rsqrt_portable(float x) {}
static inline float sk_float_rsqrt         (float x) {}

// IEEE defines how float divide behaves for non-finite values and zero-denoms, but C does not,
// so we have a helper that suppresses the possible undefined-behavior warnings.
#ifdef SK_BUILD_FOR_WIN
#pragma warning(push)
#pragma warning(disable : 4723)
#endif
SK_NO_SANITIZE("float-divide-by-zero")
static constexpr float sk_ieee_float_divide(float numer, float denom) {}

SK_NO_SANITIZE("float-divide-by-zero")
static constexpr double sk_ieee_double_divide(double numer, double denom) {}
#ifdef SK_BUILD_FOR_WIN
#pragma warning( pop )
#endif

// Returns true iff the provided number is within a small epsilon of 0.
bool sk_double_nearly_zero(double a);

// Compare two doubles and return true if they are within maxUlpsDiff of each other.
// * nan as a or b - returns false.
// * infinity, infinity or -infinity, -infinity - returns true.
// * infinity and any other number - returns false.
//
// ulp is an initialism for Units in the Last Place.
bool sk_doubles_nearly_equal_ulps(double a, double b, uint8_t maxUlpsDiff = 16);

#endif