1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2006 The Android Open Source Project
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#ifndef SkScalar_DEFINED
9cb93a386Sopenharmony_ci#define SkScalar_DEFINED
10cb93a386Sopenharmony_ci
11cb93a386Sopenharmony_ci#include "include/private/SkFloatingPoint.h"
12cb93a386Sopenharmony_ci
13cb93a386Sopenharmony_ci#undef SK_SCALAR_IS_FLOAT
14cb93a386Sopenharmony_ci#define SK_SCALAR_IS_FLOAT  1
15cb93a386Sopenharmony_ci
16cb93a386Sopenharmony_citypedef float SkScalar;
17cb93a386Sopenharmony_ci
18cb93a386Sopenharmony_ci#define SK_Scalar1                  1.0f
19cb93a386Sopenharmony_ci#define SK_ScalarHalf               0.5f
20cb93a386Sopenharmony_ci#define SK_ScalarSqrt2              SK_FloatSqrt2
21cb93a386Sopenharmony_ci#define SK_ScalarPI                 SK_FloatPI
22cb93a386Sopenharmony_ci#define SK_ScalarTanPIOver8         0.414213562f
23cb93a386Sopenharmony_ci#define SK_ScalarRoot2Over2         0.707106781f
24cb93a386Sopenharmony_ci#define SK_ScalarMax                3.402823466e+38f
25cb93a386Sopenharmony_ci#define SK_ScalarInfinity           SK_FloatInfinity
26cb93a386Sopenharmony_ci#define SK_ScalarNegativeInfinity   SK_FloatNegativeInfinity
27cb93a386Sopenharmony_ci#define SK_ScalarNaN                SK_FloatNaN
28cb93a386Sopenharmony_ci
29cb93a386Sopenharmony_ci#define SkScalarFloorToScalar(x)    sk_float_floor(x)
30cb93a386Sopenharmony_ci#define SkScalarCeilToScalar(x)     sk_float_ceil(x)
31cb93a386Sopenharmony_ci#define SkScalarRoundToScalar(x)    sk_float_floor((x) + 0.5f)
32cb93a386Sopenharmony_ci#define SkScalarTruncToScalar(x)    sk_float_trunc(x)
33cb93a386Sopenharmony_ci
34cb93a386Sopenharmony_ci#define SkScalarFloorToInt(x)       sk_float_floor2int(x)
35cb93a386Sopenharmony_ci#define SkScalarCeilToInt(x)        sk_float_ceil2int(x)
36cb93a386Sopenharmony_ci#define SkScalarRoundToInt(x)       sk_float_round2int(x)
37cb93a386Sopenharmony_ci
38cb93a386Sopenharmony_ci#define SkScalarAbs(x)              sk_float_abs(x)
39cb93a386Sopenharmony_ci#define SkScalarCopySign(x, y)      sk_float_copysign(x, y)
40cb93a386Sopenharmony_ci#define SkScalarMod(x, y)           sk_float_mod(x,y)
41cb93a386Sopenharmony_ci#define SkScalarSqrt(x)             sk_float_sqrt(x)
42cb93a386Sopenharmony_ci#define SkScalarPow(b, e)           sk_float_pow(b, e)
43cb93a386Sopenharmony_ci
44cb93a386Sopenharmony_ci#define SkScalarSin(radians)        (float)sk_float_sin(radians)
45cb93a386Sopenharmony_ci#define SkScalarCos(radians)        (float)sk_float_cos(radians)
46cb93a386Sopenharmony_ci#define SkScalarTan(radians)        (float)sk_float_tan(radians)
47cb93a386Sopenharmony_ci#define SkScalarASin(val)           (float)sk_float_asin(val)
48cb93a386Sopenharmony_ci#define SkScalarACos(val)           (float)sk_float_acos(val)
49cb93a386Sopenharmony_ci#define SkScalarATan2(y, x)         (float)sk_float_atan2(y,x)
50cb93a386Sopenharmony_ci#define SkScalarExp(x)              (float)sk_float_exp(x)
51cb93a386Sopenharmony_ci#define SkScalarLog(x)              (float)sk_float_log(x)
52cb93a386Sopenharmony_ci#define SkScalarLog2(x)             (float)sk_float_log2(x)
53cb93a386Sopenharmony_ci
54cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////////////////////////
55cb93a386Sopenharmony_ci
56cb93a386Sopenharmony_ci#define SkIntToScalar(x)        static_cast<SkScalar>(x)
57cb93a386Sopenharmony_ci#define SkIntToFloat(x)         static_cast<float>(x)
58cb93a386Sopenharmony_ci#define SkScalarTruncToInt(x)   sk_float_saturate2int(x)
59cb93a386Sopenharmony_ci
60cb93a386Sopenharmony_ci#define SkScalarToFloat(x)      static_cast<float>(x)
61cb93a386Sopenharmony_ci#define SkFloatToScalar(x)      static_cast<SkScalar>(x)
62cb93a386Sopenharmony_ci#define SkScalarToDouble(x)     static_cast<double>(x)
63cb93a386Sopenharmony_ci#define SkDoubleToScalar(x)     sk_double_to_float(x)
64cb93a386Sopenharmony_ci
65cb93a386Sopenharmony_ci#define SK_ScalarMin            (-SK_ScalarMax)
66cb93a386Sopenharmony_ci
67cb93a386Sopenharmony_cistatic inline bool SkScalarIsNaN(SkScalar x) { return x != x; }
68cb93a386Sopenharmony_ci
69cb93a386Sopenharmony_ci/** Returns true if x is not NaN and not infinite
70cb93a386Sopenharmony_ci */
71cb93a386Sopenharmony_cistatic inline bool SkScalarIsFinite(SkScalar x) { return sk_float_isfinite(x); }
72cb93a386Sopenharmony_ci
73cb93a386Sopenharmony_cistatic inline bool SkScalarsAreFinite(SkScalar a, SkScalar b) {
74cb93a386Sopenharmony_ci    return sk_floats_are_finite(a, b);
75cb93a386Sopenharmony_ci}
76cb93a386Sopenharmony_ci
77cb93a386Sopenharmony_cistatic inline bool SkScalarsAreFinite(const SkScalar array[], int count) {
78cb93a386Sopenharmony_ci    return sk_floats_are_finite(array, count);
79cb93a386Sopenharmony_ci}
80cb93a386Sopenharmony_ci
81cb93a386Sopenharmony_ci/**
82cb93a386Sopenharmony_ci *  Variant of SkScalarRoundToInt, that performs the rounding step (adding 0.5) explicitly using
83cb93a386Sopenharmony_ci *  double, to avoid possibly losing the low bit(s) of the answer before calling floor().
84cb93a386Sopenharmony_ci *
85cb93a386Sopenharmony_ci *  This routine will likely be slower than SkScalarRoundToInt(), and should only be used when the
86cb93a386Sopenharmony_ci *  extra precision is known to be valuable.
87cb93a386Sopenharmony_ci *
88cb93a386Sopenharmony_ci *  In particular, this catches the following case:
89cb93a386Sopenharmony_ci *      SkScalar x = 0.49999997;
90cb93a386Sopenharmony_ci *      int ix = SkScalarRoundToInt(x);
91cb93a386Sopenharmony_ci *      SkASSERT(0 == ix);    // <--- fails
92cb93a386Sopenharmony_ci *      ix = SkDScalarRoundToInt(x);
93cb93a386Sopenharmony_ci *      SkASSERT(0 == ix);    // <--- succeeds
94cb93a386Sopenharmony_ci */
95cb93a386Sopenharmony_cistatic inline int SkDScalarRoundToInt(SkScalar x) {
96cb93a386Sopenharmony_ci    double xx = x;
97cb93a386Sopenharmony_ci    xx += 0.5;
98cb93a386Sopenharmony_ci    return (int)floor(xx);
99cb93a386Sopenharmony_ci}
100cb93a386Sopenharmony_ci
101cb93a386Sopenharmony_ci/** Returns the fractional part of the scalar. */
102cb93a386Sopenharmony_cistatic inline SkScalar SkScalarFraction(SkScalar x) {
103cb93a386Sopenharmony_ci    return x - SkScalarTruncToScalar(x);
104cb93a386Sopenharmony_ci}
105cb93a386Sopenharmony_ci
106cb93a386Sopenharmony_cistatic inline SkScalar SkScalarSquare(SkScalar x) { return x * x; }
107cb93a386Sopenharmony_ci
108cb93a386Sopenharmony_ci#define SkScalarInvert(x)           sk_ieee_float_divide_TODO_IS_DIVIDE_BY_ZERO_SAFE_HERE(SK_Scalar1, (x))
109cb93a386Sopenharmony_ci#define SkScalarAve(a, b)           (((a) + (b)) * SK_ScalarHalf)
110cb93a386Sopenharmony_ci#define SkScalarHalf(a)             ((a) * SK_ScalarHalf)
111cb93a386Sopenharmony_ci
112cb93a386Sopenharmony_ci#define SkDegreesToRadians(degrees) ((degrees) * (SK_ScalarPI / 180))
113cb93a386Sopenharmony_ci#define SkRadiansToDegrees(radians) ((radians) * (180 / SK_ScalarPI))
114cb93a386Sopenharmony_ci
115cb93a386Sopenharmony_cistatic inline bool SkScalarIsInt(SkScalar x) {
116cb93a386Sopenharmony_ci    return x == SkScalarFloorToScalar(x);
117cb93a386Sopenharmony_ci}
118cb93a386Sopenharmony_ci
119cb93a386Sopenharmony_ci/**
120cb93a386Sopenharmony_ci *  Returns -1 || 0 || 1 depending on the sign of value:
121cb93a386Sopenharmony_ci *  -1 if x < 0
122cb93a386Sopenharmony_ci *   0 if x == 0
123cb93a386Sopenharmony_ci *   1 if x > 0
124cb93a386Sopenharmony_ci */
125cb93a386Sopenharmony_cistatic inline int SkScalarSignAsInt(SkScalar x) {
126cb93a386Sopenharmony_ci    return x < 0 ? -1 : (x > 0);
127cb93a386Sopenharmony_ci}
128cb93a386Sopenharmony_ci
129cb93a386Sopenharmony_ci// Scalar result version of above
130cb93a386Sopenharmony_cistatic inline SkScalar SkScalarSignAsScalar(SkScalar x) {
131cb93a386Sopenharmony_ci    return x < 0 ? -SK_Scalar1 : ((x > 0) ? SK_Scalar1 : 0);
132cb93a386Sopenharmony_ci}
133cb93a386Sopenharmony_ci
134cb93a386Sopenharmony_ci#define SK_ScalarNearlyZero         (SK_Scalar1 / (1 << 12))
135cb93a386Sopenharmony_ci
136cb93a386Sopenharmony_cistatic inline bool SkScalarNearlyZero(SkScalar x,
137cb93a386Sopenharmony_ci                                      SkScalar tolerance = SK_ScalarNearlyZero) {
138cb93a386Sopenharmony_ci    SkASSERT(tolerance >= 0);
139cb93a386Sopenharmony_ci    return SkScalarAbs(x) <= tolerance;
140cb93a386Sopenharmony_ci}
141cb93a386Sopenharmony_ci
142cb93a386Sopenharmony_cistatic inline bool SkScalarNearlyEqual(SkScalar x, SkScalar y,
143cb93a386Sopenharmony_ci                                       SkScalar tolerance = SK_ScalarNearlyZero) {
144cb93a386Sopenharmony_ci    SkASSERT(tolerance >= 0);
145cb93a386Sopenharmony_ci    return SkScalarAbs(x-y) <= tolerance;
146cb93a386Sopenharmony_ci}
147cb93a386Sopenharmony_ci
148cb93a386Sopenharmony_cistatic inline float SkScalarSinSnapToZero(SkScalar radians) {
149cb93a386Sopenharmony_ci    float v = SkScalarSin(radians);
150cb93a386Sopenharmony_ci    return SkScalarNearlyZero(v) ? 0.0f : v;
151cb93a386Sopenharmony_ci}
152cb93a386Sopenharmony_ci
153cb93a386Sopenharmony_cistatic inline float SkScalarCosSnapToZero(SkScalar radians) {
154cb93a386Sopenharmony_ci    float v = SkScalarCos(radians);
155cb93a386Sopenharmony_ci    return SkScalarNearlyZero(v) ? 0.0f : v;
156cb93a386Sopenharmony_ci}
157cb93a386Sopenharmony_ci
158cb93a386Sopenharmony_ci/** Linearly interpolate between A and B, based on t.
159cb93a386Sopenharmony_ci    If t is 0, return A
160cb93a386Sopenharmony_ci    If t is 1, return B
161cb93a386Sopenharmony_ci    else interpolate.
162cb93a386Sopenharmony_ci    t must be [0..SK_Scalar1]
163cb93a386Sopenharmony_ci*/
164cb93a386Sopenharmony_cistatic inline SkScalar SkScalarInterp(SkScalar A, SkScalar B, SkScalar t) {
165cb93a386Sopenharmony_ci    SkASSERT(t >= 0 && t <= SK_Scalar1);
166cb93a386Sopenharmony_ci    return A + (B - A) * t;
167cb93a386Sopenharmony_ci}
168cb93a386Sopenharmony_ci
169cb93a386Sopenharmony_ci/** Interpolate along the function described by (keys[length], values[length])
170cb93a386Sopenharmony_ci    for the passed searchKey. SearchKeys outside the range keys[0]-keys[Length]
171cb93a386Sopenharmony_ci    clamp to the min or max value. This function assumes the number of pairs
172cb93a386Sopenharmony_ci    (length) will be small and a linear search is used.
173cb93a386Sopenharmony_ci
174cb93a386Sopenharmony_ci    Repeated keys are allowed for discontinuous functions (so long as keys is
175cb93a386Sopenharmony_ci    monotonically increasing). If key is the value of a repeated scalar in
176cb93a386Sopenharmony_ci    keys the first one will be used.
177cb93a386Sopenharmony_ci*/
178cb93a386Sopenharmony_ciSkScalar SkScalarInterpFunc(SkScalar searchKey, const SkScalar keys[],
179cb93a386Sopenharmony_ci                            const SkScalar values[], int length);
180cb93a386Sopenharmony_ci
181cb93a386Sopenharmony_ci// warning: comparing floating point with == or != is unsafe
182cb93a386Sopenharmony_ci// storing and comparing against same constants ok.
183cb93a386Sopenharmony_ci#if defined(__clang__)
184cb93a386Sopenharmony_ci#pragma clang diagnostic ignored "-Wfloat-equal"
185cb93a386Sopenharmony_ci#elif defined(__GNUC__)
186cb93a386Sopenharmony_ci#pragma GCC diagnostic ignored "-Wfloat-equal"
187cb93a386Sopenharmony_ci#endif
188cb93a386Sopenharmony_ci/*
189cb93a386Sopenharmony_ci *  Helper to compare an array of scalars.
190cb93a386Sopenharmony_ci */
191cb93a386Sopenharmony_cistatic inline bool SkScalarsEqual(const SkScalar a[], const SkScalar b[], int n) {
192cb93a386Sopenharmony_ci    SkASSERT(n >= 0);
193cb93a386Sopenharmony_ci    for (int i = 0; i < n; ++i) {
194cb93a386Sopenharmony_ci        if (a[i] != b[i]) {
195cb93a386Sopenharmony_ci            return false;
196cb93a386Sopenharmony_ci        }
197cb93a386Sopenharmony_ci    }
198cb93a386Sopenharmony_ci    return true;
199cb93a386Sopenharmony_ci}
200cb93a386Sopenharmony_ci
201cb93a386Sopenharmony_ci#endif
202