blob: 6cca44e958295fbaf58f151ca0aefab4bc23f7f9 [file] [log] [blame]
reed@google.com4b163ed2012-08-07 21:35:13 +00001/*
2 * Copyright 2012 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#ifndef SkMathPriv_DEFINED
9#define SkMathPriv_DEFINED
10
11#include "SkMath.h"
12
bungeman4760f322015-06-24 13:08:51 -070013#if defined(SK_BUILD_FOR_IOS) && (defined(SK_BUILD_FOR_ARM32) || defined(SK_BUILD_FOR_ARM64))
14// iOS on ARM starts processes with the Flush-To-Zero (FTZ) and
15// Denormals-Are-Zero (DAZ) bits in the fpscr register set.
caryclark936b7342014-07-11 12:14:51 -070016// Algorithms that rely on denormalized numbers need alternative implementations.
bungeman4760f322015-06-24 13:08:51 -070017// This can also be controlled in SSE with the MXCSR register,
18// x87 with FSTCW/FLDCW, and mips with FCSR. This should be detected at runtime,
19// or the library built one way or the other more generally (by the build).
20#define SK_CPU_FLUSH_TO_ZERO
caryclark936b7342014-07-11 12:14:51 -070021#endif
22
reed@google.com4b163ed2012-08-07 21:35:13 +000023/** Returns -1 if n < 0, else returns 0
24 */
25#define SkExtractSign(n) ((int32_t)(n) >> 31)
26
27/** If sign == -1, returns -n, else sign must be 0, and returns n.
28 Typically used in conjunction with SkExtractSign().
29 */
30static inline int32_t SkApplySign(int32_t n, int32_t sign) {
31 SkASSERT(sign == 0 || sign == -1);
32 return (n ^ sign) - sign;
33}
34
35/** Return x with the sign of y */
36static inline int32_t SkCopySign32(int32_t x, int32_t y) {
37 return SkApplySign(x, SkExtractSign(x ^ y));
38}
39
40/** Given a positive value and a positive max, return the value
41 pinned against max.
42 Note: only works as long as max - value doesn't wrap around
43 @return max if value >= max, else value
44 */
45static inline unsigned SkClampUMax(unsigned value, unsigned max) {
reed@google.com4b163ed2012-08-07 21:35:13 +000046 if (value > max) {
47 value = max;
48 }
49 return value;
reed@google.com4b163ed2012-08-07 21:35:13 +000050}
51
reed@google.com4b163ed2012-08-07 21:35:13 +000052///////////////////////////////////////////////////////////////////////////////
53
54/** Return a*b/255, truncating away any fractional bits. Only valid if both
55 a and b are 0..255
56 */
57static inline U8CPU SkMulDiv255Trunc(U8CPU a, U8CPU b) {
58 SkASSERT((uint8_t)a == a);
59 SkASSERT((uint8_t)b == b);
mtklein38484272015-08-07 08:48:12 -070060 unsigned prod = a*b + 1;
reed@google.com4b163ed2012-08-07 21:35:13 +000061 return (prod + (prod >> 8)) >> 8;
62}
63
64/** Return (a*b)/255, taking the ceiling of any fractional bits. Only valid if
65 both a and b are 0..255. The expected result equals (a * b + 254) / 255.
66 */
67static inline U8CPU SkMulDiv255Ceiling(U8CPU a, U8CPU b) {
68 SkASSERT((uint8_t)a == a);
69 SkASSERT((uint8_t)b == b);
mtklein38484272015-08-07 08:48:12 -070070 unsigned prod = a*b + 255;
reed@google.com4b163ed2012-08-07 21:35:13 +000071 return (prod + (prod >> 8)) >> 8;
72}
73
74/** Just the rounding step in SkDiv255Round: round(value / 255)
75 */
76static inline unsigned SkDiv255Round(unsigned prod) {
77 prod += 128;
78 return (prod + (prod >> 8)) >> 8;
79}
80
reed353c1482016-01-21 15:29:10 -080081static inline float SkPinToUnitFloat(float x) {
82 return SkTMin(SkTMax(x, 0.0f), 1.0f);
83}
84
reed@google.com4b163ed2012-08-07 21:35:13 +000085#endif