190e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung/* 290e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung * Copyright 2015 The Android Open Source Project 390e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung * 490e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung * Licensed under the Apache License, Version 2.0 (the "License"); 590e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung * you may not use this file except in compliance with the License. 690e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung * You may obtain a copy of the License at 790e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung * 890e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung * http://www.apache.org/licenses/LICENSE-2.0 990e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung * 1090e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung * Unless required by applicable law or agreed to in writing, software 1190e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung * distributed under the License is distributed on an "AS IS" BASIS, 1290e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1390e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung * See the License for the specific language governing permissions and 1490e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung * limitations under the License. 1590e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung */ 1690e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung 1790e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung#ifndef ANDROID_MODULO_H 1890e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung#define ANDROID_MODULO_H 1990e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung 2090e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hungnamespace android { 2190e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung 2290e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// Modulo class is used for intentionally wrapping variables such as 2390e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// counters and timers. 2490e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// 2590e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// It may also be used for variables whose computation depends on the 2690e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// associativity of addition or subtraction. 2790e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// 2890e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// Features: 2990e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// 1) Modulo checks type sizes before performing operations to ensure 3090e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// that the wrap points match. This is critical for safe modular arithmetic. 3190e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// 2) Modulo returns Modulo types from arithmetic operations, thereby 3290e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// avoiding unintentional use in a non-modular computation. A Modulo 3390e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// type is converted to its base non-Modulo type through the value() function. 3490e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// 3) Modulo separates out overflowable types from non-overflowable types. 3590e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// A signed overflow is technically undefined in C and C++. 3690e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// Modulo types do not participate in sanitization. 3790e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// 4) Modulo comparisons are based on signed differences to account for wrap; 3890e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// this is not the same as the direct comparison of values. 3990e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// 5) Safe use of binary arithmetic operations relies on conversions of 4090e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// signed operands to unsigned operands (which are modular arithmetic safe). 4190e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// Conversions which are implementation-defined are assumed to use 2's complement 4290e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// representation. (See A, B, C, D from the ISO/IEC FDIS 14882 4390e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// Information technology — Programming languages — C++). 4490e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// 4590e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// A: ISO/IEC 14882:2011(E) p84 section 4.7 Integral conversions 4690e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// (2) If the destination type is unsigned, the resulting value is the least unsigned 4790e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// integer congruent to the source integer (modulo 2^n where n is the number of bits 4890e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// used to represent the unsigned type). [ Note: In a two’s complement representation, 4990e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// this conversion is conceptual and there is no change in the bit pattern (if there 5090e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// is no truncation). — end note ] 5190e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// (3) If the destination type is signed, the value is unchanged if it can be represented 5290e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// in the destination type (and bit-field width); otherwise, the value is 5390e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// implementation-defined. 5490e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// 5590e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// B: ISO/IEC 14882:2011(E) p88 section 5 Expressions 5690e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// (9) Many binary operators that expect operands of arithmetic or enumeration type 5790e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// cause conversions and yield result types in a similar way. The purpose is to 5890e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// yield a common type, which is also the type of the result. This pattern is called 5990e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// the usual arithmetic conversions, which are defined as follows: 6090e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// [...] 6190e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// Otherwise, if both operands have signed integer types or both have unsigned 6290e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// integer types, the operand with the type of lesser integer conversion rank shall be 6390e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// converted to the type of the operand with greater rank. 6490e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// — Otherwise, if the operand that has unsigned integer type has rank greater than 6590e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// or equal to the rank of the type of the other operand, the operand with signed 6690e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// integer type shall be converted to the type of the operand with unsigned integer type. 6790e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// 6890e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// C: ISO/IEC 14882:2011(E) p86 section 4.13 Integer conversion rank 6990e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// [...] The rank of long long int shall be greater than the rank of long int, 7090e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// which shall be greater than the rank of int, which shall be greater than the 7190e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// rank of short int, which shall be greater than the rank of signed char. 7290e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// — The rank of any unsigned integer type shall equal the rank of the corresponding 7390e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// signed integer type. 7490e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// 7590e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// D: ISO/IEC 14882:2011(E) p75 section 3.9.1 Fundamental types 7690e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// [...] Unsigned integers, declared unsigned, shall obey the laws of arithmetic modulo 7790e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// 2^n where n is the number of bits in the value representation of that particular 7890e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// size of integer. 7990e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// 8090e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// Note: 8190e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// Other libraries do exist for safe integer operations which can detect the 8290e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// possibility of overflow (SafeInt from MS and safe-iop in android). 8390e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung// Signed safe computation is also possible from the art header safe_math.h. 8490e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung 8590e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hungtemplate <typename T> class Modulo { 8690e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung T mValue; 8790e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung 8890e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hungpublic: 8990e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung typedef typename std::make_signed<T>::type signedT; 9090e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung typedef typename std::make_unsigned<T>::type unsignedT; 9190e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung 9290e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung Modulo() { } // intentionally uninitialized data 9390e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung Modulo(const T &value) { mValue = value; } 9490e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung const T & value() const { return mValue; } // not assignable 9590e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung signedT signedValue() const { return mValue; } 9690e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung unsignedT unsignedValue() const { return mValue; } 9790e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung void getValue(T *value) const { *value = mValue; } // more type safe than value() 9890e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung 9990e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung // modular operations valid only if size of T <= size of S. 10090e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung template <typename S> 10190e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung __attribute__((no_sanitize("integer"))) 10290e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung Modulo<T> operator +=(const Modulo<S> &other) { 10390e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung static_assert(sizeof(T) <= sizeof(S), "argument size mismatch"); 10490e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung mValue += other.unsignedValue(); 10590e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung return *this; 10690e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung } 10790e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung 10890e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung template <typename S> 10990e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung __attribute__((no_sanitize("integer"))) 11090e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung Modulo<T> operator -=(const Modulo<S> &other) { 11190e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung static_assert(sizeof(T) <= sizeof(S), "argument size mismatch"); 11290e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung mValue -= other.unsignedValue(); 11390e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung return *this; 11490e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung } 11590e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung 11690e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung // modular operations resulting in a value valid only at the smaller of the two 11790e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung // Modulo base type sizes, but we only allow equal sizes to avoid confusion. 11890e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung template <typename S> 11990e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung __attribute__((no_sanitize("integer"))) 12090e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung const Modulo<T> operator +(const Modulo<S> &other) const { 12190e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung static_assert(sizeof(T) == sizeof(S), "argument size mismatch"); 12290e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung return Modulo<T>(mValue + other.unsignedValue()); 12390e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung } 12490e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung 12590e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung template <typename S> 12690e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung __attribute__((no_sanitize("integer"))) 12790e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung const Modulo<T> operator -(const Modulo<S> &other) const { 12890e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung static_assert(sizeof(T) == sizeof(S), "argument size mismatch"); 12990e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung return Modulo<T>(mValue - other.unsignedValue()); 13090e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung } 13190e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung 13290e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung // modular operations that should be checked only at the smaller of 13390e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung // the two type sizes, but we only allow equal sizes to avoid confusion. 13490e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung // 13590e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung // Caution: These relational and comparison operations are not equivalent to 13690e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung // the base type operations. 13790e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung template <typename S> 13890e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung __attribute__((no_sanitize("integer"))) 13990e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung bool operator >(const Modulo<S> &other) const { 14090e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung static_assert(sizeof(T) == sizeof(S), "argument size mismatch"); 14190e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung return static_cast<signedT>(mValue - other.unsignedValue()) > 0; 14290e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung } 14390e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung 14490e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung template <typename S> 14590e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung __attribute__((no_sanitize("integer"))) 14690e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung bool operator >=(const Modulo<S> &other) const { 14790e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung static_assert(sizeof(T) == sizeof(S), "argument size mismatch"); 14890e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung return static_cast<signedT>(mValue - other.unsignedValue()) >= 0; 14990e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung } 15090e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung 15190e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung template <typename S> 15290e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung __attribute__((no_sanitize("integer"))) 15390e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung bool operator ==(const Modulo<S> &other) const { 15490e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung static_assert(sizeof(T) == sizeof(S), "argument size mismatch"); 15590e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung return static_cast<signedT>(mValue - other.unsignedValue()) == 0; 15690e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung } 15790e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung 15890e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung template <typename S> 15990e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung __attribute__((no_sanitize("integer"))) 16090e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung bool operator <=(const Modulo<S> &other) const { 16190e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung static_assert(sizeof(T) == sizeof(S), "argument size mismatch"); 16290e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung return static_cast<signedT>(mValue - other.unsignedValue()) <= 0; 16390e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung } 16490e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung 16590e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung template <typename S> 16690e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung __attribute__((no_sanitize("integer"))) 16790e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung bool operator <(const Modulo<S> &other) const { 16890e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung static_assert(sizeof(T) == sizeof(S), "argument size mismatch"); 16990e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung return static_cast<signedT>(mValue - other.unsignedValue()) < 0; 17090e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung } 17190e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung 17290e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung 17390e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung // modular operations with a non-Modulo type allowed with wrapping 17490e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung // because there should be no confusion as to the meaning. 17590e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung template <typename S> 17690e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung __attribute__((no_sanitize("integer"))) 17790e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung Modulo<T> operator +=(const S &other) { 17890e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung mValue += unsignedT(other); 17990e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung return *this; 18090e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung } 18190e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung 18290e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung template <typename S> 18390e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung __attribute__((no_sanitize("integer"))) 18490e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung Modulo<T> operator -=(const S &other) { 18590e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung mValue -= unsignedT(other); 18690e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung return *this; 18790e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung } 18890e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung 18990e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung // modular operations with a non-Modulo type allowed with wrapping, 19090e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung // but we restrict this only when size of T is greater than or equal to 19190e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung // the size of S to avoid confusion with the nature of overflow. 19290e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung // 19390e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung // Use of this follows left-associative style. 19490e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung // 19590e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung // Note: a Modulo type may be promoted by using "differences" off of 19690e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung // a larger sized type, but we do not automate this. 19790e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung template <typename S> 19890e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung __attribute__((no_sanitize("integer"))) 19990e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung const Modulo<T> operator +(const S &other) const { 20090e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung static_assert(sizeof(T) >= sizeof(S), "argument size mismatch"); 20190e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung return Modulo<T>(mValue + unsignedT(other)); 20290e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung } 20390e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung 20490e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung template <typename S> 20590e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung __attribute__((no_sanitize("integer"))) 20690e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung const Modulo<T> operator -(const S &other) const { 20790e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung static_assert(sizeof(T) >= sizeof(S), "argument size mismatch"); 20890e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung return Modulo<T>(mValue - unsignedT(other)); 20990e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung } 21090e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung 21190e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung // multiply is intentionally omitted, but it is a common operator in 21290e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung // modular arithmetic. 21390e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung 21490e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung // shift operations are intentionally omitted, but perhaps useful. 21590e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung // For example, left-shifting a negative number is undefined in C++11. 21690e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung}; 21790e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung 21890e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung} // namespace android 21990e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung 22090e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung#endif /* ANDROID_MODULO_H */ 221