SkMath.h revision 4b163ed2c22facbe8891616874ae07ba7827d9c9
1 2/* 3 * Copyright 2006 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10#ifndef SkMath_DEFINED 11#define SkMath_DEFINED 12 13#include "SkTypes.h" 14 15/** 16 * Computes numer1 * numer2 / denom in full 64 intermediate precision. 17 * It is an error for denom to be 0. There is no special handling if 18 * the result overflows 32bits. 19 */ 20int32_t SkMulDiv(int32_t numer1, int32_t numer2, int32_t denom); 21 22/** 23 * Computes (numer1 << shift) / denom in full 64 intermediate precision. 24 * It is an error for denom to be 0. There is no special handling if 25 * the result overflows 32bits. 26 */ 27int32_t SkDivBits(int32_t numer, int32_t denom, int shift); 28 29/** 30 * Return the integer square root of value, with a bias of bitBias 31 */ 32int32_t SkSqrtBits(int32_t value, int bitBias); 33 34/////////////////////////////////////////////////////////////////////////////// 35 36//! Returns the number of leading zero bits (0...32) 37int SkCLZ_portable(uint32_t); 38 39#if defined(__arm__) 40 #define SkCLZ(x) __builtin_clz(x) 41#endif 42 43#ifndef SkCLZ 44 #define SkCLZ(x) SkCLZ_portable(x) 45#endif 46 47/** 48 * Returns (value < 0 ? 0 : value) efficiently (i.e. no compares or branches) 49 */ 50static inline int SkClampPos(int value) { 51 return value & ~(value >> 31); 52} 53 54/** Given an integer and a positive (max) integer, return the value 55 * pinned against 0 and max, inclusive. 56 * @param value The value we want returned pinned between [0...max] 57 * @param max The positive max value 58 * @return 0 if value < 0, max if value > max, else value 59 */ 60static inline int SkClampMax(int value, int max) { 61 // ensure that max is positive 62 SkASSERT(max >= 0); 63 if (value < 0) { 64 value = 0; 65 } 66 if (value > max) { 67 value = max; 68 } 69 return value; 70} 71 72/** 73 * Returns the smallest power-of-2 that is >= the specified value. If value 74 * is already a power of 2, then it is returned unchanged. It is undefined 75 * if value is <= 0. 76 */ 77static inline int SkNextPow2(int value) { 78 SkASSERT(value > 0); 79 return 1 << (32 - SkCLZ(value - 1)); 80} 81 82/** 83 * Returns the log2 of the specified value, were that value to be rounded up 84 * to the next power of 2. It is undefined to pass 0. Examples: 85 * SkNextLog2(1) -> 0 86 * SkNextLog2(2) -> 1 87 * SkNextLog2(3) -> 2 88 * SkNextLog2(4) -> 2 89 * SkNextLog2(5) -> 3 90 */ 91static inline int SkNextLog2(uint32_t value) { 92 SkASSERT(value != 0); 93 return 32 - SkCLZ(value - 1); 94} 95 96/** 97 * Returns true if value is a power of 2. Does not explicitly check for 98 * value <= 0. 99 */ 100static inline bool SkIsPow2(int value) { 101 return (value & (value - 1)) == 0; 102} 103 104/////////////////////////////////////////////////////////////////////////////// 105 106/** 107 * SkMulS16(a, b) multiplies a * b, but requires that a and b are both int16_t. 108 * With this requirement, we can generate faster instructions on some 109 * architectures. 110 */ 111#ifdef SK_ARM_HAS_EDSP 112 static inline int32_t SkMulS16(S16CPU x, S16CPU y) { 113 SkASSERT((int16_t)x == x); 114 SkASSERT((int16_t)y == y); 115 int32_t product; 116 asm("smulbb %0, %1, %2 \n" 117 : "=r"(product) 118 : "r"(x), "r"(y) 119 ); 120 return product; 121 } 122#else 123 #ifdef SK_DEBUG 124 static inline int32_t SkMulS16(S16CPU x, S16CPU y) { 125 SkASSERT((int16_t)x == x); 126 SkASSERT((int16_t)y == y); 127 return x * y; 128 } 129 #else 130 #define SkMulS16(x, y) ((x) * (y)) 131 #endif 132#endif 133 134/** 135 * Return a*b/((1 << shift) - 1), rounding any fractional bits. 136 * Only valid if a and b are unsigned and <= 32767 and shift is > 0 and <= 8 137 */ 138static inline unsigned SkMul16ShiftRound(unsigned a, unsigned b, int shift) { 139 SkASSERT(a <= 32767); 140 SkASSERT(b <= 32767); 141 SkASSERT(shift > 0 && shift <= 8); 142 unsigned prod = SkMulS16(a, b) + (1 << (shift - 1)); 143 return (prod + (prod >> shift)) >> shift; 144} 145 146/** 147 * Return a*b/255, rounding any fractional bits. Only valid if both 148 * a and b are 0..255 149 */ 150static inline U8CPU SkMulDiv255Round(U8CPU a, U8CPU b) { 151 SkASSERT((uint8_t)a == a); 152 SkASSERT((uint8_t)b == b); 153 unsigned prod = SkMulS16(a, b) + 128; 154 return (prod + (prod >> 8)) >> 8; 155} 156 157#endif 158 159