| /* include/corecg/SkMath.h |
| ** |
| ** Copyright 2006, Google Inc. |
| ** |
| ** Licensed under the Apache License, Version 2.0 (the "License"); |
| ** you may not use this file except in compliance with the License. |
| ** You may obtain a copy of the License at |
| ** |
| ** http://www.apache.org/licenses/LICENSE-2.0 |
| ** |
| ** Unless required by applicable law or agreed to in writing, software |
| ** distributed under the License is distributed on an "AS IS" BASIS, |
| ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| ** See the License for the specific language governing permissions and |
| ** limitations under the License. |
| */ |
| |
| #ifndef SkMath_DEFINED |
| #define SkMath_DEFINED |
| |
| #include "SkTypes.h" |
| |
| /** \file SkMath.h |
| |
| This file defines various math types and functions. It also introduces |
| SkScalar, the type used to describe fractional values and coordinates. |
| SkScalar is defined at compile time to be either an IEEE float, or a |
| 16.16 fixed point integer. Various macros and functions in SkMath.h |
| allow arithmetic operations to be performed on SkScalars without known |
| which representation is being used. e.g. SkScalarMul(a, b) multiplies |
| two SkScalar values, and returns a SkScalar, and this works with either |
| float or fixed implementations. |
| */ |
| |
| int SkCLZ_portable(uint32_t); //<! Returns the number of leading zero bits (0...32) |
| |
| /** Computes the 64bit product of a * b, and then shifts the answer down by |
| shift bits, returning the low 32bits. shift must be [0..63] |
| e.g. to perform a fixedmul, call SkMulShift(a, b, 16) |
| */ |
| int32_t SkMulShift(int32_t a, int32_t b, unsigned shift); |
| /** Computes numer1 * numer2 / denom in full 64 intermediate precision. |
| It is an error for denom to be 0. There is no special handling if |
| the result overflows 32bits. |
| */ |
| int32_t SkMulDiv(int32_t numer1, int32_t numer2, int32_t denom); |
| /** Computes (numer1 << shift) / denom in full 64 intermediate precision. |
| It is an error for denom to be 0. There is no special handling if |
| the result overflows 32bits. |
| */ |
| int32_t SkDivBits(int32_t numer, int32_t denom, int shift); |
| int32_t SkSqrtBits(int32_t value, int bits); |
| #define SkSqrt32(n) SkSqrtBits(n, 15) |
| int32_t SkCubeRootBits(int32_t value, int bits); |
| |
| /** Returns -1 if n < 0, else returns 0 |
| */ |
| #define SkExtractSign(n) ((int32_t)(n) >> 31) |
| |
| /** If sign == -1, returns -n, else sign must be 0, and returns n. |
| Typically used in conjunction with SkExtractSign(). |
| */ |
| inline int32_t SkApplySign(int32_t n, int32_t sign) |
| { |
| SkASSERT(sign == 0 || sign == -1); |
| return (n ^ sign) - sign; |
| } |
| |
| /** Returns max(value, 0) |
| */ |
| inline int SkClampPos(int value) |
| { |
| return value & ~(value >> 31); |
| } |
| |
| /** Given an integer and a positive (max) integer, return the value |
| pinned against 0 and max, inclusive. |
| Note: only works as long as max - value doesn't wrap around |
| @param value The value we want returned pinned between [0...max] |
| @param max The positive max value |
| @return 0 if value < 0, max if value > max, else value |
| */ |
| inline int SkClampMax(int value, int max) |
| { |
| // ensure that max is positive |
| SkASSERT(max >= 0); |
| // ensure that if value is negative, max - value doesn't wrap around |
| SkASSERT(value >= 0 || max - value > 0); |
| |
| #ifdef SK_CPU_HAS_CONDITIONAL_INSTR |
| if (value < 0) |
| value = 0; |
| if (value > max) |
| value = max; |
| return value; |
| #else |
| |
| int diff = max - value; |
| // clear diff if diff is positive |
| diff &= diff >> 31; |
| |
| // clear the result if value < 0 |
| return (value + diff) & ~(value >> 31); |
| #endif |
| } |
| |
| /** Given a positive value and a positive max, return the value |
| pinned against max. |
| Note: only works as long as max - value doesn't wrap around |
| @return max if value >= max, else value |
| */ |
| inline unsigned SkClampUMax(unsigned value, unsigned max) |
| { |
| #ifdef SK_CPU_HAS_CONDITIONAL_INSTR |
| if (value > max) |
| value = max; |
| return value; |
| #else |
| int diff = max - value; |
| // clear diff if diff is positive |
| diff &= diff >> 31; |
| |
| return value + diff; |
| #endif |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////////// |
| |
| #if defined(__arm__) |
| #define SkCLZ(x) __builtin_clz(x) |
| #endif |
| |
| #ifndef SkCLZ |
| #define SkCLZ(x) SkCLZ_portable(x) |
| #endif |
| |
| ////////////////////////////////////////////////////////////////////////////////// |
| |
| #include "SkFixed.h" |
| #include "SkScalar.h" |
| |
| #ifdef SK_DEBUG |
| class SkMath { |
| public: |
| static void UnitTest(); |
| }; |
| #endif |
| |
| #endif |
| |