File indexing completed on 2024-05-12 15:59:36

0001 /*
0002  *  SPDX-FileCopyrightText: 2005 Adrian Page <adrian@pagenet.plus.com>
0003  *
0004  * SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #ifndef KO_INTEGER_MATHS_H
0008 #define KO_INTEGER_MATHS_H
0009 
0010 #include <cstdint>
0011 
0012 #ifndef UINT8_MAX
0013 #define UINT8_MAX 255u
0014 #endif
0015 
0016 #ifndef UINT8_MIN
0017 #define UINT8_MIN 0u
0018 #endif
0019 
0020 #ifndef UINT16_MAX
0021 #define UINT16_MAX 65535u
0022 #endif
0023 
0024 #ifndef UINT16_MIN
0025 #define UINT16_MIN 0u
0026 #endif
0027 
0028 #ifndef UINT32_MAX
0029 #define UINT32_MAX (4294967295u)
0030 #endif
0031 
0032 #ifndef UINT32_MIN
0033 #define UINT32_MIN 0u
0034 #endif
0035 
0036 #ifndef INT16_MAX
0037 #define INT16_MAX 32767
0038 #endif
0039 
0040 #ifndef INT16_MIN
0041 #define INT16_MIN -32768
0042 #endif
0043 
0044 typedef unsigned int uint;
0045 
0046 template<typename _T_, typename _T2_, typename _T3_>
0047 inline _T_ CLAMP(_T_ x, _T2_ l, _T3_ u)
0048 {
0049     if (x < l)
0050         return _T_(l);
0051     else if (x > u)
0052         return _T_(u);
0053     return x;
0054 }
0055 
0056 /// take a and scale it up by 256*b/255
0057 inline uint UINT8_SCALEBY(uint a, uint b)
0058 {
0059     uint c = a * b + 0x80u;
0060     return (c >> 8) + c;
0061 }
0062 
0063 /// multiplication of two scale values
0064 /// A scale value is interpreted as 255 equaling 1.0 (such as seen in rgb8 triplets)
0065 /// thus "255*255=255" because 1.0*1.0=1.0
0066 inline uint UINT8_MULT(uint a, uint b)
0067 {
0068     uint c = a * b + 0x80u;
0069     return ((c >> 8) + c) >> 8;
0070 }
0071 
0072 inline uint UINT8_DIVIDE(uint a, uint b)
0073 {
0074     uint c = (a * UINT8_MAX + (b / 2u)) / b;
0075     return c;
0076 }
0077 
0078 /// Approximation of (a * b * c + 32512) / 65025.0
0079 inline uint UINT8_MULT3(uint a, uint b, uint c)
0080 {
0081   uint t = a * b * c + 0x7F5B;
0082   return ((t >> 7) + t) >> 16;
0083 }
0084 
0085 /// Blending of two scale values as described by the alpha scale value
0086 /// A scale value is interpreted as 255 equaling 1.0 (such as seen in rgb8 triplets)
0087 /// Basically we do: a*alpha + b*(1-alpha)
0088 inline uint UINT8_BLEND(uint a, uint b, uint alpha)
0089 {
0090     // However the formula is refactored to (a-b)*alpha + b  since that saves a multiplication
0091     // Signed arithmetic is needed since a-b might be negative
0092     int c = (int(a) - int(b)) * alpha + 0x80u;
0093     c = ((c >> 8) + c) >> 8;
0094     return c + b;
0095 }
0096 
0097 inline uint UINT16_MULT(uint a, uint b)
0098 {
0099     uint c = a * b + 0x8000u;
0100     return ((c >> 16) + c) >> 16;
0101 }
0102 
0103 inline int INT16_MULT(int a, int b)
0104 {
0105     return (a*b) / INT16_MAX;
0106 }
0107 
0108 inline uint UINT16_DIVIDE(uint a, uint b)
0109 {
0110     uint c = (a * UINT16_MAX + (b / 2u)) / b;
0111     return c;
0112 }
0113 
0114 inline uint UINT16_BLEND(uint a, uint b, uint alpha)
0115 {
0116     // Basically we do a*alpha + b*(1-alpha)
0117     // However refactored to (a-b)*alpha + b  since that saves a multiplication
0118     // Signed arithmetic is needed since a-b might be negative
0119     int c = ((int(a) - int(b)) * int(alpha)) >> 16;
0120     return uint(c + b);
0121 }
0122 
0123 inline uint UINT8_TO_UINT16(uint c)
0124 {
0125     return c | (c << 8);
0126 }
0127 
0128 inline uint UINT16_TO_UINT8(uint c)
0129 {
0130     //return round(c / 257.0);
0131     //For all UINT16 this calculation is the same and a lot faster (off by c/65656 which for every c is 0)
0132     c = c - (c >> 8) + 128;
0133     return c >> 8;
0134 }
0135 
0136 inline int INT16_BLEND(int a, int b, uint alpha)
0137 {
0138     // Basically we do a*alpha + b*(1-alpha)
0139     // However refactored to (a-b)*alpha + b  since that saves a multiplication
0140     int c = ((int(a) - int(b)) * int(alpha)) >> 16;
0141     return c + b;
0142 }
0143 
0144 #endif
0145