1e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman/* 2e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman * Copyright 2015 The Android Open Source Project 3e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman * 4e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman * Licensed under the Apache License, Version 2.0 (the "License"); 5e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman * you may not use this file except in compliance with the License. 6e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman * You may obtain a copy of the License at 7e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman * 8e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman * http://www.apache.org/licenses/LICENSE-2.0 9e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman * 10e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman * Unless required by applicable law or agreed to in writing, software 11e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman * distributed under the License is distributed on an "AS IS" BASIS, 12e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman * See the License for the specific language governing permissions and 14e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman * limitations under the License. 15e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman */ 16e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman 17e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman#ifndef ANDROID_MODULO_H 18e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman#define ANDROID_MODULO_H 19e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman 20e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatramannamespace android { 21e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman 22e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// Modulo class is used for intentionally wrapping variables such as 23e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// counters and timers. 24e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// 25e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// It may also be used for variables whose computation depends on the 26e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// associativity of addition or subtraction. 27e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// 28e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// Features: 29e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// 1) Modulo checks type sizes before performing operations to ensure 30e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// that the wrap points match. This is critical for safe modular arithmetic. 31e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// 2) Modulo returns Modulo types from arithmetic operations, thereby 32e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// avoiding unintentional use in a non-modular computation. A Modulo 33e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// type is converted to its base non-Modulo type through the value() function. 34e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// 3) Modulo separates out overflowable types from non-overflowable types. 35e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// A signed overflow is technically undefined in C and C++. 36e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// Modulo types do not participate in sanitization. 37e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// 4) Modulo comparisons are based on signed differences to account for wrap; 38e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// this is not the same as the direct comparison of values. 39e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// 5) Safe use of binary arithmetic operations relies on conversions of 40e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// signed operands to unsigned operands (which are modular arithmetic safe). 41e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// Conversions which are implementation-defined are assumed to use 2's complement 42e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// representation. (See A, B, C, D from the ISO/IEC FDIS 14882 43e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// Information technology — Programming languages — C++). 44e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// 45e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// A: ISO/IEC 14882:2011(E) p84 section 4.7 Integral conversions 46e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// (2) If the destination type is unsigned, the resulting value is the least unsigned 47e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// integer congruent to the source integer (modulo 2^n where n is the number of bits 48e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// used to represent the unsigned type). [ Note: In a two’s complement representation, 49e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// this conversion is conceptual and there is no change in the bit pattern (if there 50e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// is no truncation). — end note ] 51e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// (3) If the destination type is signed, the value is unchanged if it can be represented 52e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// in the destination type (and bit-field width); otherwise, the value is 53e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// implementation-defined. 54e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// 55e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// B: ISO/IEC 14882:2011(E) p88 section 5 Expressions 56e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// (9) Many binary operators that expect operands of arithmetic or enumeration type 57e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// cause conversions and yield result types in a similar way. The purpose is to 58e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// yield a common type, which is also the type of the result. This pattern is called 59e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// the usual arithmetic conversions, which are defined as follows: 60e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// [...] 61e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// Otherwise, if both operands have signed integer types or both have unsigned 62e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// integer types, the operand with the type of lesser integer conversion rank shall be 63e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// converted to the type of the operand with greater rank. 64e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// — Otherwise, if the operand that has unsigned integer type has rank greater than 65e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// or equal to the rank of the type of the other operand, the operand with signed 66e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// integer type shall be converted to the type of the operand with unsigned integer type. 67e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// 68e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// C: ISO/IEC 14882:2011(E) p86 section 4.13 Integer conversion rank 69e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// [...] The rank of long long int shall be greater than the rank of long int, 70e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// which shall be greater than the rank of int, which shall be greater than the 71e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// rank of short int, which shall be greater than the rank of signed char. 72e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// — The rank of any unsigned integer type shall equal the rank of the corresponding 73e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// signed integer type. 74e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// 75e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// D: ISO/IEC 14882:2011(E) p75 section 3.9.1 Fundamental types 76e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// [...] Unsigned integers, declared unsigned, shall obey the laws of arithmetic modulo 77e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// 2^n where n is the number of bits in the value representation of that particular 78e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// size of integer. 79e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// 80e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// Note: 81e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// Other libraries do exist for safe integer operations which can detect the 82e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// possibility of overflow (SafeInt from MS and safe-iop in android). 83e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman// Signed safe computation is also possible from the art header safe_math.h. 84e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman 85e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatramantemplate <typename T> class Modulo { 86e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman T mValue; 87e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman 88e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatramanpublic: 89e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman typedef typename std::make_signed<T>::type signedT; 90e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman typedef typename std::make_unsigned<T>::type unsignedT; 91e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman 92e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman Modulo() { } // intentionally uninitialized data 93e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman Modulo(const T &value) { mValue = value; } 94e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman const T & value() const { return mValue; } // not assignable 95e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman signedT signedValue() const { return mValue; } 96e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman unsignedT unsignedValue() const { return mValue; } 97e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman void getValue(T *value) const { *value = mValue; } // more type safe than value() 98e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman 99e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman // modular operations valid only if size of T <= size of S. 100e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman template <typename S> 101e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman __attribute__((no_sanitize("integer"))) 102e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman Modulo<T> operator +=(const Modulo<S> &other) { 103e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman static_assert(sizeof(T) <= sizeof(S), "argument size mismatch"); 104e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman mValue += other.unsignedValue(); 105e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman return *this; 106e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman } 107e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman 108e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman template <typename S> 109e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman __attribute__((no_sanitize("integer"))) 110e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman Modulo<T> operator -=(const Modulo<S> &other) { 111e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman static_assert(sizeof(T) <= sizeof(S), "argument size mismatch"); 112e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman mValue -= other.unsignedValue(); 113e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman return *this; 114e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman } 115e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman 116e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman // modular operations resulting in a value valid only at the smaller of the two 117e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman // Modulo base type sizes, but we only allow equal sizes to avoid confusion. 118e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman template <typename S> 119e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman __attribute__((no_sanitize("integer"))) 120e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman const Modulo<T> operator +(const Modulo<S> &other) const { 121e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman static_assert(sizeof(T) == sizeof(S), "argument size mismatch"); 122e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman return Modulo<T>(mValue + other.unsignedValue()); 123e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman } 124e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman 125e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman template <typename S> 126e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman __attribute__((no_sanitize("integer"))) 127e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman const Modulo<T> operator -(const Modulo<S> &other) const { 128e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman static_assert(sizeof(T) == sizeof(S), "argument size mismatch"); 129e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman return Modulo<T>(mValue - other.unsignedValue()); 130e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman } 131e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman 132e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman // modular operations that should be checked only at the smaller of 133e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman // the two type sizes, but we only allow equal sizes to avoid confusion. 134e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman // 135e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman // Caution: These relational and comparison operations are not equivalent to 136e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman // the base type operations. 137e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman template <typename S> 138e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman __attribute__((no_sanitize("integer"))) 139e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman bool operator >(const Modulo<S> &other) const { 140e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman static_assert(sizeof(T) == sizeof(S), "argument size mismatch"); 141e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman return static_cast<signedT>(mValue - other.unsignedValue()) > 0; 142e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman } 143e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman 144e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman template <typename S> 145e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman __attribute__((no_sanitize("integer"))) 146e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman bool operator >=(const Modulo<S> &other) const { 147e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman static_assert(sizeof(T) == sizeof(S), "argument size mismatch"); 148e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman return static_cast<signedT>(mValue - other.unsignedValue()) >= 0; 149e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman } 150e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman 151e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman template <typename S> 152e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman __attribute__((no_sanitize("integer"))) 153e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman bool operator ==(const Modulo<S> &other) const { 154e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman static_assert(sizeof(T) == sizeof(S), "argument size mismatch"); 155e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman return static_cast<signedT>(mValue - other.unsignedValue()) == 0; 156e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman } 157e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman 158e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman template <typename S> 159e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman __attribute__((no_sanitize("integer"))) 160e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman bool operator <=(const Modulo<S> &other) const { 161e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman static_assert(sizeof(T) == sizeof(S), "argument size mismatch"); 162e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman return static_cast<signedT>(mValue - other.unsignedValue()) <= 0; 163e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman } 164e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman 165e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman template <typename S> 166e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman __attribute__((no_sanitize("integer"))) 167e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman bool operator <(const Modulo<S> &other) const { 168e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman static_assert(sizeof(T) == sizeof(S), "argument size mismatch"); 169e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman return static_cast<signedT>(mValue - other.unsignedValue()) < 0; 170e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman } 171e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman 172e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman 173e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman // modular operations with a non-Modulo type allowed with wrapping 174e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman // because there should be no confusion as to the meaning. 175e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman template <typename S> 176e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman __attribute__((no_sanitize("integer"))) 177e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman Modulo<T> operator +=(const S &other) { 178e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman mValue += unsignedT(other); 179e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman return *this; 180e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman } 181e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman 182e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman template <typename S> 183e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman __attribute__((no_sanitize("integer"))) 184e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman Modulo<T> operator -=(const S &other) { 185e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman mValue -= unsignedT(other); 186e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman return *this; 187e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman } 188e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman 189e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman // modular operations with a non-Modulo type allowed with wrapping, 190e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman // but we restrict this only when size of T is greater than or equal to 191e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman // the size of S to avoid confusion with the nature of overflow. 192e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman // 193e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman // Use of this follows left-associative style. 194e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman // 195e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman // Note: a Modulo type may be promoted by using "differences" off of 196e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman // a larger sized type, but we do not automate this. 197e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman template <typename S> 198e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman __attribute__((no_sanitize("integer"))) 199e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman const Modulo<T> operator +(const S &other) const { 200e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman static_assert(sizeof(T) >= sizeof(S), "argument size mismatch"); 201e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman return Modulo<T>(mValue + unsignedT(other)); 202e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman } 203e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman 204e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman template <typename S> 205e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman __attribute__((no_sanitize("integer"))) 206e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman const Modulo<T> operator -(const S &other) const { 207e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman static_assert(sizeof(T) >= sizeof(S), "argument size mismatch"); 208e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman return Modulo<T>(mValue - unsignedT(other)); 209e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman } 210e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman 211e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman // multiply is intentionally omitted, but it is a common operator in 212e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman // modular arithmetic. 213e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman 214e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman // shift operations are intentionally omitted, but perhaps useful. 215e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman // For example, left-shifting a negative number is undefined in C++11. 216e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman}; 217e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman 218e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman} // namespace android 219e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman 220e2b43843fd12783188edd2c54188ea8d26864788Vijay Venkatraman#endif /* ANDROID_MODULO_H */ 221