SkMath.h revision 1c980e0d7772f05f570ae0227d91635f017c2227
10910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/*
20910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
30910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *
40910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
50910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * you may not use this file except in compliance with the License.
60910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * You may obtain a copy of the License at
70910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *
80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
90910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *
100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * See the License for the specific language governing permissions and
140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * limitations under the License.
150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */
160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifndef SkMath_DEFINED
180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkMath_DEFINED
190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkTypes.h"
210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project//! Returns the number of leading zero bits (0...32)
230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectint SkCLZ_portable(uint32_t);
240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Computes the 64bit product of a * b, and then shifts the answer down by
260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    shift bits, returning the low 32bits. shift must be [0..63]
270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    e.g. to perform a fixedmul, call SkMulShift(a, b, 16)
280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/
290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectint32_t SkMulShift(int32_t a, int32_t b, unsigned shift);
300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Computes numer1 * numer2 / denom in full 64 intermediate precision.
320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    It is an error for denom to be 0. There is no special handling if
330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    the result overflows 32bits.
340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/
350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectint32_t SkMulDiv(int32_t numer1, int32_t numer2, int32_t denom);
360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Computes (numer1 << shift) / denom in full 64 intermediate precision.
380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    It is an error for denom to be 0. There is no special handling if
390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    the result overflows 32bits.
400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/
410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectint32_t SkDivBits(int32_t numer, int32_t denom, int shift);
420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Return the integer square root of value, with a bias of bitBias
440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/
450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectint32_t SkSqrtBits(int32_t value, int bitBias);
460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Return the integer square root of n, treated as a SkFixed (16.16)
480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/
490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkSqrt32(n)         SkSqrtBits(n, 15)
500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Return the integer cube root of value, with a bias of bitBias
520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */
530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectint32_t SkCubeRootBits(int32_t value, int bitBias);
540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Returns -1 if n < 0, else returns 0
560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/
570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkExtractSign(n)    ((int32_t)(n) >> 31)
580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** If sign == -1, returns -n, else sign must be 0, and returns n.
600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    Typically used in conjunction with SkExtractSign().
610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/
620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline int32_t SkApplySign(int32_t n, int32_t sign) {
630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(sign == 0 || sign == -1);
640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return (n ^ sign) - sign;
650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
671c980e0d7772f05f570ae0227d91635f017c2227Mike Reed/** Return x with the sign of y */
681c980e0d7772f05f570ae0227d91635f017c2227Mike Reedstatic inline int32_t SkCopySign32(int32_t x, int32_t y) {
691c980e0d7772f05f570ae0227d91635f017c2227Mike Reed    return SkApplySign(x, SkExtractSign(x ^ y));
701c980e0d7772f05f570ae0227d91635f017c2227Mike Reed}
711c980e0d7772f05f570ae0227d91635f017c2227Mike Reed
720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Returns (value < 0 ? 0 : value) efficiently (i.e. no compares or branches)
730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/
740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline int SkClampPos(int value) {
750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return value & ~(value >> 31);
760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Given an integer and a positive (max) integer, return the value
790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    pinned against 0 and max, inclusive.
800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    Note: only works as long as max - value doesn't wrap around
810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    @param value    The value we want returned pinned between [0...max]
820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    @param max      The positive max value
830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    @return 0 if value < 0, max if value > max, else value
840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/
850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline int SkClampMax(int value, int max) {
860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // ensure that max is positive
870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(max >= 0);
880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // ensure that if value is negative, max - value doesn't wrap around
890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(value >= 0 || max - value > 0);
900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_CPU_HAS_CONDITIONAL_INSTR
920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (value < 0) {
930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        value = 0;
940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (value > max) {
960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        value = max;
970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return value;
990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#else
1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int diff = max - value;
1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // clear diff if diff is positive
1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    diff &= diff >> 31;
1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // clear the result if value < 0
1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return (value + diff) & ~(value >> 31);
1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Given a positive value and a positive max, return the value
1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    pinned against max.
1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    Note: only works as long as max - value doesn't wrap around
1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    @return max if value >= max, else value
1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/
1150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline unsigned SkClampUMax(unsigned value, unsigned max) {
1160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_CPU_HAS_CONDITIONAL_INSTR
1170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (value > max) {
1180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        value = max;
1190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return value;
1210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#else
1220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int diff = max - value;
1230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // clear diff if diff is positive
1240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    diff &= diff >> 31;
1250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return value + diff;
1270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
1310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#if defined(__arm__) && !defined(__thumb__)
1330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    #define SkCLZ(x)    __builtin_clz(x)
1340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
1350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifndef SkCLZ
1370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    #define SkCLZ(x)    SkCLZ_portable(x)
1380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
1390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
1410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Returns the smallest power-of-2 that is >= the specified value. If value
1430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    is already a power of 2, then it is returned unchanged. It is undefined
1440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if value is <= 0.
1450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/
1460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline int SkNextPow2(int value) {
1470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(value > 0);
1480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return 1 << (32 - SkCLZ(value - 1));
1490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Returns the log2 of the specified value, were that value to be rounded up
1520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    to the next power of 2. It is undefined to pass 0. Examples:
1530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project         SkNextLog2(1) -> 0
1540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project         SkNextLog2(2) -> 1
1550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project         SkNextLog2(3) -> 2
1560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project         SkNextLog2(4) -> 2
1570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project         SkNextLog2(5) -> 3
1580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/
1590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline int SkNextLog2(uint32_t value) {
1600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(value != 0);
1610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return 32 - SkCLZ(value - 1);
1620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
1650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** SkMulS16(a, b) multiplies a * b, but requires that a and b are both int16_t.
1670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    With this requirement, we can generate faster instructions on some
1680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    architectures.
1690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/
1703026a9ec59b285412941d278a570e382088f8adaMike Reed#if defined(__arm__) \
1713026a9ec59b285412941d278a570e382088f8adaMike Reed  && !defined(__thumb__) \
172396008a4fc955119355c57bc41a3d9119c8e22d6Jean-Baptiste Queru  && !defined(__ARM_ARCH_4T__) \
1733026a9ec59b285412941d278a570e382088f8adaMike Reed  && !defined(__ARM_ARCH_5T__)
1740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    static inline int32_t SkMulS16(S16CPU x, S16CPU y) {
1750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT((int16_t)x == x);
1760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT((int16_t)y == y);
1770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int32_t product;
1780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        asm("smulbb %0, %1, %2 \n"
1790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            : "=r"(product)
1800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            : "r"(x), "r"(y)
1810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            );
1820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return product;
1830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#else
1850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    #ifdef SK_DEBUG
1860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        static inline int32_t SkMulS16(S16CPU x, S16CPU y) {
1870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT((int16_t)x == x);
1880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT((int16_t)y == y);
1890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return x * y;
1900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
1910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    #else
1920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        #define SkMulS16(x, y)  ((x) * (y))
1930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    #endif
1940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
1950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Return a*b/255, truncating away any fractional bits. Only valid if both
1970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    a and b are 0..255
1980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/
1990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline U8CPU SkMulDiv255Trunc(U8CPU a, U8CPU b) {
2000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT((uint8_t)a == a);
2010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT((uint8_t)b == b);
2020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned prod = SkMulS16(a, b) + 1;
2030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return (prod + (prod >> 8)) >> 8;
2040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Return a*b/255, rounding any fractional bits. Only valid if both
2070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    a and b are 0..255
2080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */
2090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline U8CPU SkMulDiv255Round(U8CPU a, U8CPU b) {
2100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT((uint8_t)a == a);
2110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT((uint8_t)b == b);
2120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned prod = SkMulS16(a, b) + 128;
2130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return (prod + (prod >> 8)) >> 8;
2140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Return a*b/((1 << shift) - 1), rounding any fractional bits.
2170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    Only valid if a and b are unsigned and <= 32767 and shift is > 0 and <= 8
2180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/
2190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline unsigned SkMul16ShiftRound(unsigned a, unsigned b, int shift) {
2200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(a <= 32767);
2210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(b <= 32767);
2220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(shift > 0 && shift <= 8);
2230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned prod = SkMulS16(a, b) + (1 << (shift - 1));
2240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return (prod + (prod >> shift)) >> shift;
2250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2279f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed/** Just the rounding step in SkDiv255Round: round(value / 255)
2289f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed */
2299f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reedstatic inline unsigned SkDiv255Round(unsigned prod) {
2309f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    prod += 128;
2319f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    return (prod + (prod >> 8)) >> 8;
2329f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed}
2339f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed
2340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
2350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
236