Home | History | Annotate | Download | only in foundation
      1 /*
      2  * Copyright 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef A_UTILS_H_
     18 
     19 #define A_UTILS_H_
     20 
     21 /* ============================ math templates ============================ */
     22 
     23 /* T must be integer type, den must not be 0 */
     24 template<class T>
     25 inline static const T divRound(const T &num, const T &den) {
     26     if ((num >= 0) ^ (den >= 0)) {
     27         return (num - den / 2) / den;
     28     } else {
     29         return (num + den / 2) / den;
     30     }
     31 }
     32 
     33 /* == ceil(num / den). T must be integer type, den must not be 0 */
     34 template<class T>
     35 inline static const T divUp(const T &num, const T &den) {
     36     if (den < 0) {
     37         return (num < 0 ? num + den + 1 : num) / den;
     38     } else {
     39         return (num < 0 ? num : num + den - 1) / den;
     40     }
     41 }
     42 
     43 /* == ceil(num / den) * den. T must be integer type, alignment must be positive power of 2 */
     44 template<class T, class U>
     45 inline static const T align(const T &num, const U &den) {
     46     return (num + (T)(den - 1)) & (T)~(den - 1);
     47 }
     48 
     49 template<class T>
     50 inline static T abs(const T &a) {
     51     return a < 0 ? -a : a;
     52 }
     53 
     54 template<class T>
     55 inline static const T &min(const T &a, const T &b) {
     56     return a < b ? a : b;
     57 }
     58 
     59 template<class T>
     60 inline static const T &max(const T &a, const T &b) {
     61     return a > b ? a : b;
     62 }
     63 
     64 template<class T>
     65 void ENSURE_UNSIGNED_TYPE() {
     66     T TYPE_MUST_BE_UNSIGNED[(T)-1 < 0 ? -1 : 0] __unused;
     67 }
     68 
     69 // needle is in range [hayStart, hayStart + haySize)
     70 template<class T, class U>
     71 __attribute__((no_sanitize("integer")))
     72 inline static bool isInRange(const T &hayStart, const U &haySize, const T &needle) {
     73     ENSURE_UNSIGNED_TYPE<U>();
     74     return (T)(hayStart + haySize) >= hayStart && needle >= hayStart && (U)(needle - hayStart) < haySize;
     75 }
     76 
     77 // [needleStart, needleStart + needleSize) is in range [hayStart, hayStart + haySize)
     78 template<class T, class U>
     79 __attribute__((no_sanitize("integer")))
     80 inline static bool isInRange(
     81         const T &hayStart, const U &haySize, const T &needleStart, const U &needleSize) {
     82     ENSURE_UNSIGNED_TYPE<U>();
     83     return isInRange(hayStart, haySize, needleStart)
     84             && (T)(needleStart + needleSize) >= needleStart
     85             && (U)(needleStart + needleSize - hayStart) <= haySize;
     86 }
     87 
     88 /* T must be integer type, period must be positive */
     89 template<class T>
     90 inline static T periodicError(const T &val, const T &period) {
     91     T err = abs(val) % period;
     92     return (err < (period / 2)) ? err : (period - err);
     93 }
     94 
     95 #endif  // A_UTILS_H_
     96