1 /////////////////////////////////////////////////////////////////////////// 2 // 3 // Copyright (c) 2009, Industrial Light & Magic, a division of Lucas 4 // Digital Ltd. LLC 5 // 6 // All rights reserved. 7 // 8 // Redistribution and use in source and binary forms, with or without 9 // modification, are permitted provided that the following conditions are 10 // met: 11 // * Redistributions of source code must retain the above copyright 12 // notice, this list of conditions and the following disclaimer. 13 // * Redistributions in binary form must reproduce the above 14 // copyright notice, this list of conditions and the following disclaimer 15 // in the documentation and/or other materials provided with the 16 // distribution. 17 // * Neither the name of Industrial Light & Magic nor the names of 18 // its contributors may be used to endorse or promote products derived 19 // from this software without specific prior written permission. 20 // 21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 // 33 /////////////////////////////////////////////////////////////////////////// 34 35 #ifndef INCLUDED_IMF_CHECKED_ARITHMETIC_H 36 #define INCLUDED_IMF_CHECKED_ARITHMETIC_H 37 38 //----------------------------------------------------------------------------- 39 // 40 // Integer arithmetic operations that throw exceptions 41 // on overflow, underflow or division by zero. 42 // 43 //----------------------------------------------------------------------------- 44 45 #include <limits> 46 #include <IexMathExc.h> 47 48 namespace Imf { 49 50 template <bool b> struct StaticAssertionFailed; 51 template <> struct StaticAssertionFailed <true> {}; 52 53 #define IMF_STATIC_ASSERT(x) \ 54 do {StaticAssertionFailed <x> staticAssertionFailed;} while (false) 55 56 57 template <class T> 58 T 59 uiMult (T a, T b) 60 { 61 // 62 // Unsigned integer multiplication 63 // 64 65 IMF_STATIC_ASSERT (!std::numeric_limits<T>::is_signed && 66 std::numeric_limits<T>::is_integer); 67 68 if (a > 0 && b > std::numeric_limits<T>::max() / a) 69 throw Iex::OverflowExc ("Integer multiplication overflow."); 70 71 return a * b; 72 } 73 74 75 template <class T> 76 T 77 uiDiv (T a, T b) 78 { 79 // 80 // Unsigned integer division 81 // 82 83 IMF_STATIC_ASSERT (!std::numeric_limits<T>::is_signed && 84 std::numeric_limits<T>::is_integer); 85 86 if (b == 0) 87 throw Iex::DivzeroExc ("Integer division by zero."); 88 89 return a / b; 90 } 91 92 93 template <class T> 94 T 95 uiAdd (T a, T b) 96 { 97 // 98 // Unsigned integer addition 99 // 100 101 IMF_STATIC_ASSERT (!std::numeric_limits<T>::is_signed && 102 std::numeric_limits<T>::is_integer); 103 104 if (a > std::numeric_limits<T>::max() - b) 105 throw Iex::OverflowExc ("Integer addition overflow."); 106 107 return a + b; 108 } 109 110 111 template <class T> 112 T 113 uiSub (T a, T b) 114 { 115 // 116 // Unsigned integer subtraction 117 // 118 119 IMF_STATIC_ASSERT (!std::numeric_limits<T>::is_signed && 120 std::numeric_limits<T>::is_integer); 121 122 if (a < b) 123 throw Iex::UnderflowExc ("Integer subtraction underflow."); 124 125 return a - b; 126 } 127 128 129 template <class T> 130 size_t 131 checkArraySize (T n, size_t s) 132 { 133 // 134 // Verify that the size, in bytes, of an array with n elements 135 // of size s can be computed without overflowing: 136 // 137 // If computing 138 // 139 // size_t (n) * s 140 // 141 // would overflow, then throw an Iex::OverflowExc exception. 142 // Otherwise return 143 // 144 // size_t (n). 145 // 146 147 IMF_STATIC_ASSERT (!std::numeric_limits<T>::is_signed && 148 std::numeric_limits<T>::is_integer); 149 150 IMF_STATIC_ASSERT (sizeof (T) <= sizeof (size_t)); 151 152 if (size_t (n) > std::numeric_limits<size_t>::max() / s) 153 throw Iex::OverflowExc ("Integer multiplication overflow."); 154 155 return size_t (n); 156 } 157 158 159 } // namespace Imf 160 161 #endif 162