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