SkMath.h revision ea774d2a5a049bf89474c0f047ed6a4e521de126
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/** Return the integer square root of n, treated as a SkFixed (16.16) 35 */ 36#define SkSqrt32(n) SkSqrtBits(n, 15) 37 38/////////////////////////////////////////////////////////////////////////////// 39 40//! Returns the number of leading zero bits (0...32) 41int SkCLZ_portable(uint32_t); 42 43#if defined(SK_CPU_ARM) 44 #define SkCLZ(x) __builtin_clz(x) 45#endif 46 47#ifndef SkCLZ 48 #define SkCLZ(x) SkCLZ_portable(x) 49#endif 50 51/** 52 * Returns (value < 0 ? 0 : value) efficiently (i.e. no compares or branches) 53 */ 54static inline int SkClampPos(int value) { 55 return value & ~(value >> 31); 56} 57 58/** Given an integer and a positive (max) integer, return the value 59 * pinned against 0 and max, inclusive. 60 * @param value The value we want returned pinned between [0...max] 61 * @param max The positive max value 62 * @return 0 if value < 0, max if value > max, else value 63 */ 64static inline int SkClampMax(int value, int max) { 65 // ensure that max is positive 66 SkASSERT(max >= 0); 67 if (value < 0) { 68 value = 0; 69 } 70 if (value > max) { 71 value = max; 72 } 73 return value; 74} 75 76/** 77 * Returns the smallest power-of-2 that is >= the specified value. If value 78 * is already a power of 2, then it is returned unchanged. It is undefined 79 * if value is <= 0. 80 */ 81static inline int SkNextPow2(int value) { 82 SkASSERT(value > 0); 83 return 1 << (32 - SkCLZ(value - 1)); 84} 85 86/** 87 * Returns the log2 of the specified value, were that value to be rounded up 88 * to the next power of 2. It is undefined to pass 0. Examples: 89 * SkNextLog2(1) -> 0 90 * SkNextLog2(2) -> 1 91 * SkNextLog2(3) -> 2 92 * SkNextLog2(4) -> 2 93 * SkNextLog2(5) -> 3 94 */ 95static inline int SkNextLog2(uint32_t value) { 96 SkASSERT(value != 0); 97 return 32 - SkCLZ(value - 1); 98} 99 100/** 101 * Returns true if value is a power of 2. Does not explicitly check for 102 * value <= 0. 103 */ 104static inline bool SkIsPow2(int value) { 105 return (value & (value - 1)) == 0; 106} 107 108/////////////////////////////////////////////////////////////////////////////// 109 110/** 111 * SkMulS16(a, b) multiplies a * b, but requires that a and b are both int16_t. 112 * With this requirement, we can generate faster instructions on some 113 * architectures. 114 */ 115#ifdef SK_ARM_HAS_EDSP 116 static inline int32_t SkMulS16(S16CPU x, S16CPU y) { 117 SkASSERT((int16_t)x == x); 118 SkASSERT((int16_t)y == y); 119 int32_t product; 120 asm("smulbb %0, %1, %2 \n" 121 : "=r"(product) 122 : "r"(x), "r"(y) 123 ); 124 return product; 125 } 126#else 127 #ifdef SK_DEBUG 128 static inline int32_t SkMulS16(S16CPU x, S16CPU y) { 129 SkASSERT((int16_t)x == x); 130 SkASSERT((int16_t)y == y); 131 return x * y; 132 } 133 #else 134 #define SkMulS16(x, y) ((x) * (y)) 135 #endif 136#endif 137 138/** 139 * Return a*b/((1 << shift) - 1), rounding any fractional bits. 140 * Only valid if a and b are unsigned and <= 32767 and shift is > 0 and <= 8 141 */ 142static inline unsigned SkMul16ShiftRound(U16CPU a, U16CPU b, int shift) { 143 SkASSERT(a <= 32767); 144 SkASSERT(b <= 32767); 145 SkASSERT(shift > 0 && shift <= 8); 146 unsigned prod = SkMulS16(a, b) + (1 << (shift - 1)); 147 return (prod + (prod >> shift)) >> shift; 148} 149 150/** 151 * Return a*b/255, rounding any fractional bits. 152 * Only valid if a and b are unsigned and <= 32767. 153 */ 154static inline U8CPU SkMulDiv255Round(U16CPU a, U16CPU b) { 155 SkASSERT(a <= 32767); 156 SkASSERT(b <= 32767); 157 unsigned prod = SkMulS16(a, b) + 128; 158 return (prod + (prod >> 8)) >> 8; 159} 160 161#endif 162