PBRT
/home/felix/UBC/projects/AdaptiveLightfieldSampling/pbrt_v2/src/3rdparty/openexr-1.7.0/ImfCheckedArithmetic.h
00001 
00002 //
00003 // Copyright (c) 2009, Industrial Light & Magic, a division of Lucas
00004 // Digital Ltd. LLC
00005 // 
00006 // All rights reserved.
00007 // 
00008 // Redistribution and use in source and binary forms, with or without
00009 // modification, are permitted provided that the following conditions are
00010 // met:
00011 // *       Redistributions of source code must retain the above copyright
00012 // notice, this list of conditions and the following disclaimer.
00013 // *       Redistributions in binary form must reproduce the above
00014 // copyright notice, this list of conditions and the following disclaimer
00015 // in the documentation and/or other materials provided with the
00016 // distribution.
00017 // *       Neither the name of Industrial Light & Magic nor the names of
00018 // its contributors may be used to endorse or promote products derived
00019 // from this software without specific prior written permission. 
00020 // 
00021 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00024 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00025 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00026 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00027 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00028 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00029 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00030 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00031 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00032 //
00034 
00035 #ifndef INCLUDED_IMF_CHECKED_ARITHMETIC_H
00036 #define INCLUDED_IMF_CHECKED_ARITHMETIC_H
00037 
00038 //-----------------------------------------------------------------------------
00039 //
00040 //      Integer arithmetic operations that throw exceptions
00041 //      on overflow, underflow or division by zero.
00042 //
00043 //-----------------------------------------------------------------------------
00044 
00045 #include <limits>
00046 #include <IexMathExc.h>
00047 
00048 namespace Imf {
00049 
00050 template <bool b> struct StaticAssertionFailed;
00051 template <> struct StaticAssertionFailed <true> {};
00052 
00053 #define IMF_STATIC_ASSERT(x) \
00054     do {StaticAssertionFailed <x> staticAssertionFailed;} while (false)
00055 
00056 
00057 template <class T>
00058 T
00059 uiMult (T a, T b)
00060 {
00061     //
00062     // Unsigned integer multiplication
00063     //
00064 
00065     IMF_STATIC_ASSERT (!std::numeric_limits<T>::is_signed &&
00066                         std::numeric_limits<T>::is_integer);
00067 
00068     if (a > 0 && b > std::numeric_limits<T>::max() / a)
00069         throw Iex::OverflowExc ("Integer multiplication overflow.");
00070 
00071     return a * b;
00072 }
00073 
00074 
00075 template <class T>
00076 T
00077 uiDiv (T a, T b)
00078 {
00079     //
00080     // Unsigned integer division
00081     //
00082 
00083     IMF_STATIC_ASSERT (!std::numeric_limits<T>::is_signed &&
00084                         std::numeric_limits<T>::is_integer);
00085 
00086     if (b == 0)
00087         throw Iex::DivzeroExc ("Integer division by zero.");
00088 
00089     return a / b;
00090 }
00091 
00092 
00093 template <class T>
00094 T
00095 uiAdd (T a, T b)
00096 {
00097     //
00098     // Unsigned integer addition
00099     //
00100 
00101     IMF_STATIC_ASSERT (!std::numeric_limits<T>::is_signed &&
00102                         std::numeric_limits<T>::is_integer);
00103 
00104     if (a > std::numeric_limits<T>::max() - b)
00105         throw Iex::OverflowExc ("Integer addition overflow.");
00106 
00107     return a + b;
00108 }
00109 
00110 
00111 template <class T>
00112 T
00113 uiSub (T a, T b)
00114 {
00115     //
00116     // Unsigned integer subtraction
00117     //
00118 
00119     IMF_STATIC_ASSERT (!std::numeric_limits<T>::is_signed &&
00120                         std::numeric_limits<T>::is_integer);
00121 
00122     if (a < b)
00123         throw Iex::UnderflowExc ("Integer subtraction underflow.");
00124 
00125     return a - b;
00126 }
00127 
00128 
00129 template <class T>
00130 size_t
00131 checkArraySize (T n, size_t s)
00132 {
00133     //
00134     // Verify that the size, in bytes, of an array with n elements
00135     // of size s can be computed without overflowing:
00136     //
00137     // If computing
00138     //
00139     //      size_t (n) * s
00140     //
00141     // would overflow, then throw an Iex::OverflowExc exception.
00142     // Otherwise return
00143     //
00144     //      size_t (n).
00145     //
00146 
00147     IMF_STATIC_ASSERT (!std::numeric_limits<T>::is_signed &&
00148                         std::numeric_limits<T>::is_integer);
00149 
00150     IMF_STATIC_ASSERT (sizeof (T) <= sizeof (size_t));
00151 
00152     if (size_t (n) > std::numeric_limits<size_t>::max() / s)
00153         throw Iex::OverflowExc ("Integer multiplication overflow.");
00154 
00155     return size_t (n);
00156 }
00157 
00158 
00159 } // namespace Imf
00160 
00161 #endif