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