STLdoc
STLdocumentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
safeint_internal.h
Go to the documentation of this file.
1 /***
2 *safeint_internal.h - Internal details for SafeInt (see safeint.h)
3 *
4 * Copyright (c) Microsoft Corporation. All rights reserved.
5 *
6 *Purpose:
7 * Private internal details for SafeInt.
8 * The constructs and functions in Microsoft::Utilities::details are not
9 * meant to be used by external code and can change at any time.
10 *
11 ****/
12 
13 #pragma once
14 
15 #include <crtdbg.h>
16 
17 #pragma pack(push, _CRT_PACKING)
18 
19 namespace msl
20 {
21 
22 namespace utilities
23 {
24 
25 namespace details
26 {
27 #pragma warning(push)
28 #pragma warning(disable:4702)
29 
30 template < typename T > class NumericType;
31 
32 template <> class NumericType<bool> { public: enum{ isBool = true, isFloat = false, isInt = false }; };
33 template <> class NumericType<char> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
34 template <> class NumericType<unsigned char> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
35 template <> class NumericType<signed char> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
36 template <> class NumericType<short> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
37 template <> class NumericType<unsigned short> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
38 #if _NATIVE_WCHAR_T_DEFINED
39 template <> class NumericType<wchar_t> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
40 #endif /* _NATIVE_WCHAR_T_DEFINED */
41 template <> class NumericType<int> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
42 template <> class NumericType<unsigned int> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
43 template <> class NumericType<long> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
44 template <> class NumericType<unsigned long> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
45 template <> class NumericType<__int64> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
46 template <> class NumericType<unsigned __int64> { public: enum{ isBool = false, isFloat = false, isInt = true }; };
47 template <> class NumericType<float> { public: enum{ isBool = false, isFloat = true, isInt = false }; };
48 template <> class NumericType<double> { public: enum{ isBool = false, isFloat = true, isInt = false }; };
49 template <> class NumericType<long double> { public: enum{ isBool = false, isFloat = true, isInt = false }; };
50 // Catch-all for anything not supported
51 template < typename T > class NumericType { public: enum{ isBool = false, isFloat = false, isInt = false }; };
52 
53 
54 template < typename T > class IntTraits
55 {
56 public:
58  enum
59  {
60 #pragma warning(suppress:4804)
61  isSigned = ( (T)(-1) < 0 ),
62  is64Bit = ( sizeof(T) == 8 ),
63  is32Bit = ( sizeof(T) == 4 ),
64  is16Bit = ( sizeof(T) == 2 ),
65  is8Bit = ( sizeof(T) == 1 ),
66  isLT32Bit = ( sizeof(T) < 4 ),
67  isLT64Bit = ( sizeof(T) < 8 ),
68  isInt8 = ( sizeof(T) == 1 && isSigned ),
69  isUint8 = ( sizeof(T) == 1 && !isSigned ),
70  isInt16 = ( sizeof(T) == 2 && isSigned ),
71  isUint16 = ( sizeof(T) == 2 && !isSigned ),
72  isInt32 = ( sizeof(T) == 4 && isSigned ),
73  isUint32 = ( sizeof(T) == 4 && !isSigned ),
74  isInt64 = ( sizeof(T) == 8 && isSigned ),
75  isUint64 = ( sizeof(T) == 8 && !isSigned ),
76  bitCount = ( sizeof(T)*8 ),
77 #pragma warning(suppress:4804)
79  };
80 
81 #pragma warning(push)
82 #pragma warning(disable:4310)
83  const static T maxInt = isSigned ? ((T)~((T)1 << (T)(bitCount-1))) : ((T)(~(T)0));
84  const static T minInt = isSigned ? ((T)((T)1 << (T)(bitCount-1))) : ((T)0);
85 #pragma warning(pop)
86 };
87 
88 // this is strictly internal and not to be used as a policy in SafeInt<>
90 {
91  static void SafeIntOnOverflow()
92  {
93  }
94 
95  static void SafeIntOnDivZero()
96  {
97  }
98 };
99 
100 template < typename T, typename U > class SafeIntCompare
101 {
102 public:
103  enum
104  {
108  isCastOK = ((isLikeSigned && sizeof(T) >= sizeof(U)) ||
109  (IntTraits< T >::isSigned && sizeof(T) > sizeof(U))),
112  };
113 };
114 
115 template < typename U > class SafeIntCompare< float, U >
116 {
117 public:
118  enum
119  {
121  isBothUnsigned = false,
123  isCastOK = true
124  };
125 };
126 
127 template < typename U > class SafeIntCompare< double, U >
128 {
129 public:
130  enum
131  {
133  isBothUnsigned = false,
135  isCastOK = true
136  };
137 };
138 
139 template < typename U > class SafeIntCompare< long double, U >
140 {
141 public:
142  enum
143  {
145  isBothUnsigned = false,
147  isCastOK = true
148  };
149 };
150 
151 //all of the arithmetic operators can be solved by the same code within
152 //each of these regions without resorting to compile-time constant conditionals
153 //most operators collapse the problem into less than the 22 zones, but this is used
154 //as the first cut
155 //using this also helps ensure that we handle all of the possible cases correctly
156 
157 template < typename T, typename U > class IntRegion
158 {
159 public:
160  enum
161  {
162  //unsigned-unsigned zone
168  //unsigned-signed
169  IntZone_UintLT32_IntLT32 = !IntTraits< T >::isSigned && IntTraits< U >::isSigned && SafeIntCompare< T,U >::isBothLT32Bit,
174  IntZone_Uint64_Int64 = IntTraits< T >::isUint64 && IntTraits< U >::isInt64,
175  //signed-signed
180  IntZone_Int64_Int = SafeIntCompare< T,U >::isBothSigned && IntTraits< T >::is64Bit && IntTraits< U >::isLT64Bit,
182  //signed-unsigned
183  IntZone_IntLT32_UintLT32 = IntTraits< T >::isSigned && !IntTraits< U >::isSigned && SafeIntCompare< T,U >::isBothLT32Bit,
189  };
190 };
191 
192 // useful function to help with getting the magnitude of a negative number
194 {
198 };
199 
200 template < typename T >
202 {
203 public:
204  enum
205  {
208  };
209 };
210 
211 template < typename T, int Method = GetAbsMethod< T >::method > class AbsValueHelper;
212 
213 template < typename T > class AbsValueHelper < T, AbsMethodInt >
214 {
215 public:
216  static unsigned __int32 Abs( T t ) throw()
217  {
218  _ASSERTE( t < 0 );
219  return (unsigned __int32)-t;
220  }
221 };
222 
223 template < typename T > class AbsValueHelper < T, AbsMethodInt64 >
224 {
225 public:
226  static unsigned __int64 Abs( T t ) throw()
227  {
228  _ASSERTE( t < 0 );
229  return (unsigned __int64)-t;
230  }
231 };
232 
233 template < typename T > class AbsValueHelper < T, AbsMethodNoop >
234 {
235 public:
236  static T Abs( T t ) throw()
237  {
238  // Why are you calling Abs on an unsigned number ???
239  _ASSERTE( ("AbsValueHelper::Abs should not be called with an unsigned integer type", 0) );
240  return t;
241  }
242 };
243 
244 template < typename T, typename E, bool fSigned > class NegationHelper;
245 
246 template < typename T, typename E > class NegationHelper < T, E, true > // Signed
247 {
248 public:
249  static SafeIntError Negative( T t, T& ret )
250  {
251  // corner case
252  if( t != IntTraits< T >::minInt )
253  {
254  // cast prevents unneeded checks in the case of small ints
255  ret = -t;
256  return SafeIntNoError;
257  }
258  E::SafeIntOnOverflow();
260  }
261 };
262 
263 
264 template < typename T, typename E > class NegationHelper < T, E, false > // unsigned
265 {
266 public:
267  static SafeIntError Negative( T t, T& ret ) throw()
268  {
270 
271 #pragma warning(suppress:4127)
273 
274 #pragma warning(suppress:4146)
275  ret = -t;
276  return SafeIntNoError;
277  }
278 };
279 
280 //core logic to determine casting behavior
282 {
283  CastOK = 0,
291 };
292 
293 template < typename ToType, typename FromType >
295 {
296 public:
297  enum
298  {
301 
306 
310 
313  sizeof( FromType ) >= sizeof( ToType ) ) ||
315  sizeof( FromType ) > sizeof( ToType ) ) ) ? CastCheckGTMax :
316 
319  sizeof( ToType ) >= sizeof( FromType ) ) ? CastCheckLTZero :
320 
323  };
324 };
325 
326 template < typename T, typename U, typename E,
328 
329 template < typename T, typename U, typename E > class SafeCastHelper < T, U, E, CastOK >
330 {
331 public:
332  static SafeIntError Cast( U u, T& t ) throw()
333  {
334  t = (T)u;
335  return SafeIntNoError;
336  }
337 };
338 
339 // special case floats and doubles
340 // tolerate loss of precision
341 template < typename T, typename U, typename E > class SafeCastHelper < T, U, E, CastFromFloat >
342 {
343 public:
344  static SafeIntError Cast( U u, T& t )
345  {
346  if( u <= (U)IntTraits< T >::maxInt &&
347  u >= (U)IntTraits< T >::minInt )
348  {
349  t = (T)u;
350  return SafeIntNoError;
351  }
352 
353  E::SafeIntOnOverflow();
355  }
356 };
357 
358 // Match on any method where a bool is cast to type T
359 template < typename T, typename U, typename E > class SafeCastHelper < T, U, E, CastFromBool >
360 {
361 public:
362  static SafeIntError Cast( bool b, T& t ) throw()
363  {
364  t = (T)( b ? 1 : 0 );
365  return SafeIntNoError;
366  }
367 };
368 
369 template < typename T, typename U, typename E > class SafeCastHelper < T, U, E, CastToBool >
370 {
371 public:
372  static SafeIntError Cast( T t, bool& b ) throw()
373  {
374  b = !!t;
375  return SafeIntNoError;
376  }
377 };
378 
379 template < typename T, typename U, typename E > class SafeCastHelper < T, U, E, CastCheckLTZero >
380 {
381 public:
382  static SafeIntError Cast( U u, T& t )
383  {
384  if( u < 0 )
385  {
386  E::SafeIntOnOverflow();
388  }
389 
390  t = (T)u;
391  return SafeIntNoError;
392  }
393 };
394 
395 template < typename T, typename U, typename E > class SafeCastHelper < T, U, E, CastCheckGTMax >
396 {
397 public:
398  static SafeIntError Cast( U u, T& t )
399  {
400  if( u > IntTraits< T >::maxInt )
401  {
402  E::SafeIntOnOverflow();
404  }
405 
406  t = (T)u;
407  return SafeIntNoError;
408  }
409 };
410 
411 template < typename T, typename U, typename E > class SafeCastHelper < T, U, E, CastCheckMinMaxUnsigned >
412 {
413 public:
414  static SafeIntError Cast( U u, T& t )
415  {
416  // U is signed - T could be either signed or unsigned
417  if( u > IntTraits< T >::maxInt || u < 0 )
418  {
419  E::SafeIntOnOverflow();
421  }
422 
423  t = (T)u;
424  return SafeIntNoError;
425  }
426 };
427 
428 template < typename T, typename U, typename E > class SafeCastHelper < T, U, E, CastCheckMinMaxSigned >
429 {
430 public:
431  static SafeIntError Cast( U u, T& t )
432  {
433  // T, U are signed
435  {
436  E::SafeIntOnOverflow();
438  }
439 
440  t = (T)u;
441  return SafeIntNoError;
442  }
443 };
444 
445 //core logic to determine whether a comparison is valid, or needs special treatment
447 {
453 };
454 
455 template < typename T, typename U >
457 {
458 public:
459  enum
460  {
461 #if _SAFEINT_USE_ANSI_CONVERSIONS
463 #else /* _SAFEINT_USE_ANSI_CONVERSIONS */
465  ( ( IntTraits< T >::isSigned && sizeof(T) < 8 && sizeof(U) < 4 ) ||
466  ( IntTraits< U >::isSigned && sizeof(T) < 4 && sizeof(U) < 8 ) ) ? ComparisonMethod_CastInt :
467  ( ( IntTraits< T >::isSigned && sizeof(U) < 8 ) ||
468  ( IntTraits< U >::isSigned && sizeof(T) < 8 ) ) ? ComparisonMethod_CastInt64 :
471 #endif /* _SAFEINT_USE_ANSI_CONVERSIONS */
472  };
473 };
474 
475 template <typename T, typename U, int Method = ValidComparison< T, U >::method > class EqualityTest;
476 
477 template < typename T, typename U > class EqualityTest< T, U, ComparisonMethod_Ok >
478 {
479 public:
480  static bool IsEquals( const T t, const U u ) throw() { return ( t == u ); }
481 };
482 
483 template < typename T, typename U > class EqualityTest< T, U, ComparisonMethod_CastInt >
484 {
485 public:
486  static bool IsEquals( const T t, const U u ) throw() { return ( (int)t == (int)u ); }
487 };
488 
489 template < typename T, typename U > class EqualityTest< T, U, ComparisonMethod_CastInt64 >
490 {
491 public:
492  static bool IsEquals( const T t, const U u ) throw() { return ( (__int64)t == (__int64)u ); }
493 };
494 
495 template < typename T, typename U > class EqualityTest< T, U, ComparisonMethod_UnsignedT >
496 {
497 public:
498  static bool IsEquals( const T t, const U u ) throw()
499  {
500  //one operand is 32 or 64-bit unsigned, and the other is signed and the same size or smaller
501  if( u < 0 )
502  {
503  return false;
504  }
505 
506  //else safe to cast to type T
507  return ( t == (T)u );
508  }
509 };
510 
511 template < typename T, typename U > class EqualityTest< T, U, ComparisonMethod_UnsignedU>
512 {
513 public:
514  static bool IsEquals( const T t, const U u ) throw()
515  {
516  //one operand is 32 or 64-bit unsigned, and the other is signed and the same size or smaller
517  if( t < 0 )
518  {
519  return false;
520  }
521 
522  //else safe to cast to type U
523  return ( (U)t == u );
524  }
525 };
526 
527 template <typename T, typename U, int Method = ValidComparison< T, U >::method > class GreaterThanTest;
528 
529 template < typename T, typename U > class GreaterThanTest< T, U, ComparisonMethod_Ok >
530 {
531 public:
532  static bool GreaterThan( const T t, const U u ) throw() { return ( t > u ); }
533 };
534 
535 template < typename T, typename U > class GreaterThanTest< T, U, ComparisonMethod_CastInt >
536 {
537 public:
538  static bool GreaterThan( const T t, const U u ) throw() { return ( (int)t > (int)u ); }
539 };
540 
541 template < typename T, typename U > class GreaterThanTest< T, U, ComparisonMethod_CastInt64 >
542 {
543 public:
544  static bool GreaterThan( const T t, const U u ) throw() { return ( (__int64)t > (__int64)u ); }
545 };
546 
547 template < typename T, typename U > class GreaterThanTest< T, U, ComparisonMethod_UnsignedT >
548 {
549 public:
550  static bool GreaterThan( const T t, const U u ) throw()
551  {
552  // one operand is 32 or 64-bit unsigned, and the other is signed and the same size or smaller
553  if( u < 0 )
554  {
555  return SafeIntNoError;
556  }
557 
558  // else safe to cast to type T
559  return ( t > (T)u );
560  }
561 };
562 
563 template < typename T, typename U > class GreaterThanTest< T, U, ComparisonMethod_UnsignedU >
564 {
565 public:
566  static bool GreaterThan( const T t, const U u ) throw()
567  {
568  // one operand is 32 or 64-bit unsigned, and the other is signed and the same size or smaller
569  if( t < 0 )
570  {
571  return false;
572  }
573 
574  // else safe to cast to type U
575  return ( (U)t > u );
576  }
577 };
578 
579 // Modulus is simpler than comparison, but follows much the same logic
580 // using this set of functions, it can't fail except in a div 0 situation
581 template <typename T, typename U, typename E, int Method = ValidComparison< T, U >::method > class ModulusHelper;
582 
583 template <typename T, typename U, typename E> class ModulusHelper <T, U, E, ComparisonMethod_Ok>
584 {
585 public:
586  static SafeIntError Modulus( const T& t, const U& u, T& result )
587  {
588  if(u == 0)
589  {
590  E::SafeIntOnDivZero();
591  return SafeIntDivideByZero;
592  }
593 
594  // trap corner case
595 #pragma warning(suppress:4127)
597  {
598  if(u == -1)
599  {
600  result = 0;
601  return SafeIntNoError;
602  }
603  }
604 
605  result = (T)(t % u);
606  return SafeIntNoError;
607  }
608 };
609 
610 template <typename T, typename U, typename E> class ModulusHelper <T, U, E, ComparisonMethod_CastInt>
611 {
612 public:
613  static SafeIntError Modulus( const T& t, const U& u, T& result )
614  {
615  if(u == 0)
616  {
617  E::SafeIntOnDivZero();
618  return SafeIntDivideByZero;
619  }
620 
621  // trap corner case
622 #pragma warning(suppress:4127)
624  {
625  if(u == -1)
626  {
627  result = 0;
628  return SafeIntNoError;
629  }
630  }
631 
632  result = (T)(t % u);
633  return SafeIntNoError;
634  }
635 };
636 
637 template <typename T, typename U, typename E> class ModulusHelper <T, U, E, ComparisonMethod_CastInt64>
638 {
639 public:
640  static SafeIntError Modulus( const T& t, const U& u, T& result )
641  {
642  if(u == 0)
643  {
644  E::SafeIntOnDivZero();
645  return SafeIntDivideByZero;
646  }
647 
648 #pragma warning(suppress:4127)
649  if(IntTraits< U >::isSigned && u == -1)
650  {
651  result = 0;
652  }
653  else
654  {
655  result = (T)((__int64)t % (__int64)u);
656  }
657 
658  return SafeIntNoError;
659  }
660 };
661 
662 // T is unsigned __int64, U is any signed int
663 template <typename T, typename U, typename E> class ModulusHelper <T, U, E, ComparisonMethod_UnsignedT>
664 {
665 public:
666  static SafeIntError Modulus( const T& t, const U& u, T& result )
667  {
668  if(u == 0)
669  {
670  E::SafeIntOnDivZero();
671  return SafeIntDivideByZero;
672  }
673 
674  // u could be negative - if so, need to convert to positive
675  // casts below are always safe due to the way modulus works
676  if(u < 0)
677  {
678  result = (T)(t % AbsValueHelper< U >::Abs(u));
679  }
680  else
681  {
682  result = (T)(t % u);
683  }
684 
685  return SafeIntNoError;
686  }
687 };
688 
689 // U is unsigned __int64, T any signed int
690 template <typename T, typename U, typename E> class ModulusHelper <T, U, E, ComparisonMethod_UnsignedU>
691 {
692 public:
693  static SafeIntError Modulus( const T& t, const U& u, T& result )
694  {
695  if(u == 0)
696  {
697  E::SafeIntOnDivZero();
698  return SafeIntDivideByZero;
699  }
700 
701  //t could be negative - if so, need to convert to positive
702  if(t < 0)
703  {
704  result = -(T)( AbsValueHelper< T >::Abs( t ) % u );
705  }
706  else
707  {
708  result = (T)((T)t % u);
709  }
710 
711  return SafeIntNoError;
712  }
713 };
714 
715 //core logic to determine method to check multiplication
717 {
718  MultiplicationState_CastInt = 0, // One or both signed, smaller than 32-bit
719  MultiplicationState_CastInt64, // One or both signed, smaller than 64-bit
720  MultiplicationState_CastUint, // Both are unsigned, smaller than 32-bit
721  MultiplicationState_CastUint64, // Both are unsigned, both 32-bit or smaller
722  MultiplicationState_Uint64Uint, // Both are unsigned, lhs 64-bit, rhs 32-bit or smaller
723  MultiplicationState_Uint64Uint64, // Both are unsigned int64
724  MultiplicationState_Uint64Int, // lhs is unsigned int64, rhs int32
725  MultiplicationState_Uint64Int64, // lhs is unsigned int64, rhs signed int64
726  MultiplicationState_UintUint64, // Both are unsigned, lhs 32-bit or smaller, rhs 64-bit
727  MultiplicationState_UintInt64, // lhs unsigned 32-bit or less, rhs int64
728  MultiplicationState_Int64Uint, // lhs int64, rhs unsigned int32
729  MultiplicationState_Int64Int64, // lhs int64, rhs int64
730  MultiplicationState_Int64Int, // lhs int64, rhs int32
731  MultiplicationState_IntUint64, // lhs int, rhs unsigned int64
732  MultiplicationState_IntInt64, // lhs int, rhs int64
733  MultiplicationState_Int64Uint64, // lhs int64, rhs uint64
735 };
736 
737 template < typename T, typename U >
739 {
740 public:
741  enum
742  {
743  // unsigned-unsigned
751  // unsigned-signed
758  // signed-signed
765  // signed-unsigned
773  };
774 };
775 
776 template <typename T, typename U, typename E, int Method = MultiplicationMethod< T, U >::method > class MultiplicationHelper;
777 
778 template < typename T, typename U, typename E > class MultiplicationHelper< T, U, E, MultiplicationState_CastInt>
779 {
780 public:
781  //accepts signed, both less than 32-bit
782  static SafeIntError Multiply( const T& t, const U& u, T& ret )
783  {
784  int tmp = t * u;
785 
787  {
788  E::SafeIntOnOverflow();
790  }
791 
792  ret = (T)tmp;
793  return SafeIntNoError;
794  }
795 };
796 
797 template < typename T, typename U, typename E > class MultiplicationHelper< T, U, E, MultiplicationState_CastUint >
798 {
799 public:
800  //accepts unsigned, both less than 32-bit
801  static SafeIntError Multiply( const T& t, const U& u, T& ret )
802  {
803  unsigned int tmp = t * u;
804 
805  if( tmp > IntTraits< T >::maxInt )
806  {
807  E::SafeIntOnOverflow();
809  }
810 
811  ret = (T)tmp;
812  return SafeIntNoError;
813  }
814 };
815 
816 template < typename T, typename U, typename E > class MultiplicationHelper< T, U, E, MultiplicationState_CastInt64>
817 {
818 public:
819  //mixed signed or both signed where at least one argument is 32-bit, and both a 32-bit or less
820  static SafeIntError Multiply( const T& t, const U& u, T& ret )
821  {
822  __int64 tmp = (__int64)t * (__int64)u;
823 
824  if(tmp > (__int64)IntTraits< T >::maxInt || tmp < (__int64)IntTraits< T >::minInt)
825  {
826  E::SafeIntOnOverflow();
828  }
829 
830  ret = (T)tmp;
831  return SafeIntNoError;
832  }
833 };
834 
835 template < typename T, typename U, typename E > class MultiplicationHelper< T, U, E, MultiplicationState_CastUint64>
836 {
837 public:
838  //both unsigned where at least one argument is 32-bit, and both are 32-bit or less
839  static SafeIntError Multiply( const T& t, const U& u, T& ret )
840  {
841  unsigned __int64 tmp = (unsigned __int64)t * (unsigned __int64)u;
842 
843  if(tmp > (unsigned __int64)IntTraits< T >::maxInt)
844  {
845  E::SafeIntOnOverflow();
847  }
848 
849  ret = (T)tmp;
850  return SafeIntNoError;
851  }
852 };
853 
854 // T = left arg and return type
855 // U = right arg
856 template < typename T, typename U, typename E > class LargeIntRegMultiply;
857 
858 template< typename E > class LargeIntRegMultiply< unsigned __int64, unsigned __int64, E >
859 {
860 public:
861  static SafeIntError RegMultiply( const unsigned __int64& a, const unsigned __int64& b, unsigned __int64& ret )
862  {
863  unsigned __int32 aHigh, aLow, bHigh, bLow;
864 
865  // Consider that a*b can be broken up into:
866  // (aHigh * 2^32 + aLow) * (bHigh * 2^32 + bLow)
867  // => (aHigh * bHigh * 2^64) + (aLow * bHigh * 2^32) + (aHigh * bLow * 2^32) + (aLow * bLow)
868  // Note - same approach applies for 128 bit math on a 64-bit system
869 
870  aHigh = (unsigned __int32)(a >> 32);
871  aLow = (unsigned __int32)a;
872  bHigh = (unsigned __int32)(b >> 32);
873  bLow = (unsigned __int32)b;
874 
875  ret = 0;
876 
877  if(aHigh == 0)
878  {
879  if(bHigh != 0)
880  {
881  ret = (unsigned __int64)aLow * (unsigned __int64)bHigh;
882  }
883  }
884  else if(bHigh == 0)
885  {
886  if(aHigh != 0)
887  {
888  ret = (unsigned __int64)aHigh * (unsigned __int64)bLow;
889  }
890  }
891  else
892  {
893  E::SafeIntOnOverflow();
895  }
896 
897  if(ret != 0)
898  {
899  unsigned __int64 tmp;
900 
901  if((unsigned __int32)(ret >> 32) != 0)
902  {
903  E::SafeIntOnOverflow();
905  }
906 
907  ret <<= 32;
908  tmp = (unsigned __int64)aLow * (unsigned __int64)bLow;
909  ret += tmp;
910 
911  if(ret < tmp)
912  {
913  E::SafeIntOnOverflow();
915  }
916 
917  return SafeIntNoError;
918  }
919 
920  ret = (unsigned __int64)aLow * (unsigned __int64)bLow;
921  return SafeIntNoError;
922  }
923 };
924 
925 template< typename E > class LargeIntRegMultiply< unsigned __int64, unsigned __int32, E >
926 {
927 public:
928  static SafeIntError RegMultiply( const unsigned __int64& a, unsigned __int32 b, unsigned __int64& ret )
929  {
930  unsigned __int32 aHigh, aLow;
931 
932  // Consider that a*b can be broken up into:
933  // (aHigh * 2^32 + aLow) * b
934  // => (aHigh * b * 2^32) + (aLow * b)
935 
936  aHigh = (unsigned __int32)(a >> 32);
937  aLow = (unsigned __int32)a;
938 
939  ret = 0;
940 
941  if(aHigh != 0)
942  {
943  ret = (unsigned __int64)aHigh * (unsigned __int64)b;
944 
945  unsigned __int64 tmp;
946 
947  if((unsigned __int32)(ret >> 32) != 0)
948  {
949  E::SafeIntOnOverflow();
951  }
952 
953  ret <<= 32;
954  tmp = (unsigned __int64)aLow * (unsigned __int64)b;
955  ret += tmp;
956 
957  if(ret < tmp)
958  {
959  E::SafeIntOnOverflow();
961  }
962 
963  return SafeIntNoError;
964  }
965 
966  ret = (unsigned __int64)aLow * (unsigned __int64)b;
967  return SafeIntNoError;
968  }
969 };
970 
971 template< typename E > class LargeIntRegMultiply< unsigned __int64, signed __int32, E >
972 {
973 public:
974  static SafeIntError RegMultiply( const unsigned __int64& a, signed __int32 b, unsigned __int64& ret )
975  {
976  if( b < 0 && a != 0 )
977  {
978  E::SafeIntOnOverflow();
980  }
981 
983  }
984 };
985 
986 template< typename E > class LargeIntRegMultiply< unsigned __int64, signed __int64, E >
987 {
988 public:
989  static SafeIntError RegMultiply( const unsigned __int64& a, signed __int64 b, unsigned __int64& ret )
990  {
991  if( b < 0 && a != 0 )
992  {
993  E::SafeIntOnOverflow();
995  }
996 
998  }
999 };
1000 
1001 template< typename E > class LargeIntRegMultiply< signed __int32, unsigned __int64, E >
1002 {
1003 public:
1004  static SafeIntError RegMultiply( signed __int32 a, const unsigned __int64& b, signed __int32& ret )
1005  {
1006  unsigned __int32 bHigh, bLow;
1007  bool fIsNegative = false;
1008 
1009  // Consider that a*b can be broken up into:
1010  // (aHigh * 2^32 + aLow) * (bHigh * 2^32 + bLow)
1011  // => (aHigh * bHigh * 2^64) + (aLow * bHigh * 2^32) + (aHigh * bLow * 2^32) + (aLow * bLow)
1012 
1013  bHigh = (unsigned __int32)(b >> 32);
1014  bLow = (unsigned __int32)b;
1015 
1016  ret = 0;
1017 
1018  if(bHigh != 0 && a != 0)
1019  {
1020  E::SafeIntOnOverflow();
1022  }
1023 
1024  if( a < 0 )
1025  {
1026  a = -a;
1027  fIsNegative = true;
1028  }
1029 
1030  unsigned __int64 tmp = (unsigned __int32)a * (unsigned __int64)bLow;
1031 
1032 
1033  if( !fIsNegative )
1034  {
1035  if( tmp <= (unsigned __int64)IntTraits< signed __int32 >::maxInt )
1036  {
1037  ret = (signed __int32)tmp;
1038  return SafeIntNoError;
1039  }
1040  }
1041  else
1042  {
1043  if( tmp <= (unsigned __int64)IntTraits< signed __int32 >::maxInt+1 )
1044  {
1045  ret = -( (signed __int32)tmp );
1046  return SafeIntNoError;
1047  }
1048  }
1049 
1050  E::SafeIntOnOverflow();
1052  }
1053 };
1054 
1055 template < typename E > class LargeIntRegMultiply< unsigned __int32, unsigned __int64, E >
1056 {
1057 public:
1058  static SafeIntError RegMultiply( unsigned __int32 a, const unsigned __int64& b, unsigned __int32& ret )
1059  {
1060  // Consider that a*b can be broken up into:
1061  // (bHigh * 2^32 + bLow) * a
1062  // => (bHigh * a * 2^32) + (bLow * a)
1063  // In this case, the result must fit into 32-bits
1064  // If bHigh != 0 && a != 0, immediate error.
1065 
1066  if( (unsigned __int32)(b >> 32) != 0 && a != 0 )
1067  {
1068  E::SafeIntOnOverflow();
1070  }
1071 
1072  unsigned __int64 tmp = b * (unsigned __int64)a;
1073 
1074  if( (unsigned __int32)(tmp >> 32) != 0 ) // overflow
1075  {
1076  E::SafeIntOnOverflow();
1078  }
1079 
1080  ret = (unsigned __int32)tmp;
1081  return SafeIntNoError;
1082  }
1083 };
1084 
1085 template < typename E > class LargeIntRegMultiply< unsigned __int32, signed __int64, E >
1086 {
1087 public:
1088  static SafeIntError RegMultiply( unsigned __int32 a, const signed __int64& b, unsigned __int32& ret )
1089  {
1090  if( b < 0 && a != 0 )
1091  {
1092  E::SafeIntOnOverflow();
1094  }
1095 
1097  }
1098 };
1099 
1100 template < typename E > class LargeIntRegMultiply< signed __int64, signed __int64, E >
1101 {
1102 public:
1103  static SafeIntError RegMultiply( const signed __int64& a, const signed __int64& b, signed __int64& ret )
1104  {
1105  bool aNegative = false;
1106  bool bNegative = false;
1107 
1108  unsigned __int64 tmp;
1109  __int64 a1 = a;
1110  __int64 b1 = b;
1111 
1112  if( a1 < 0 )
1113  {
1114  aNegative = true;
1115  a1 = -a1;
1116  }
1117 
1118  if( b1 < 0 )
1119  {
1120  bNegative = true;
1121  b1 = -b1;
1122  }
1123 
1125  RegMultiply( (unsigned __int64)a1, (unsigned __int64)b1, (unsigned __int64)tmp ) == SafeIntNoError )
1126  {
1127  // The unsigned multiplication didn't overflow
1128  if( aNegative ^ bNegative )
1129  {
1130  // Result must be negative
1131  if( tmp <= (unsigned __int64)IntTraits< signed __int64 >::minInt )
1132  {
1133  ret = -(signed __int64)tmp;
1134  return SafeIntNoError;
1135  }
1136  }
1137  else
1138  {
1139  // Result must be positive
1140  if( tmp <= (unsigned __int64)IntTraits< signed __int64 >::maxInt )
1141  {
1142  ret = (signed __int64)tmp;
1143  return SafeIntNoError;
1144  }
1145  }
1146  }
1147 
1148  E::SafeIntOnOverflow();
1150  }
1151 };
1152 
1153 template < typename E > class LargeIntRegMultiply< signed __int64, unsigned __int32, E >
1154 {
1155 public:
1156  static SafeIntError RegMultiply( const signed __int64& a, unsigned __int32 b, signed __int64& ret )
1157  {
1158  bool aNegative = false;
1159  unsigned __int64 tmp;
1160  __int64 a1 = a;
1161 
1162  if( a1 < 0 )
1163  {
1164  aNegative = true;
1165  a1 = -a1;
1166  }
1167 
1169  {
1170  // The unsigned multiplication didn't overflow
1171  if( aNegative )
1172  {
1173  // Result must be negative
1174  if( tmp <= (unsigned __int64)IntTraits< signed __int64 >::minInt )
1175  {
1176  ret = -(signed __int64)tmp;
1177  return SafeIntNoError;
1178  }
1179  }
1180  else
1181  {
1182  // Result must be positive
1183  if( tmp <= (unsigned __int64)IntTraits< signed __int64 >::maxInt )
1184  {
1185  ret = (signed __int64)tmp;
1186  return SafeIntNoError;
1187  }
1188  }
1189  }
1190 
1191  E::SafeIntOnOverflow();
1193  }
1194 };
1195 
1196 template < typename E > class LargeIntRegMultiply< signed __int64, signed __int32, E >
1197 {
1198 public:
1199  static SafeIntError RegMultiply( const signed __int64& a, signed __int32 b, signed __int64& ret )
1200  {
1201  bool aNegative = false;
1202  bool bNegative = false;
1203 
1204  unsigned __int64 tmp;
1205  __int64 a1 = a;
1206  __int64 b1 = b;
1207 
1208  if( a1 < 0 )
1209  {
1210  aNegative = true;
1211  a1 = -a1;
1212  }
1213 
1214  if( b1 < 0 )
1215  {
1216  bNegative = true;
1217  b1 = -b1;
1218  }
1219 
1221  RegMultiply( (unsigned __int64)a1, (unsigned __int32)b1, (unsigned __int64)tmp ) == SafeIntNoError )
1222  {
1223  // The unsigned multiplication didn't overflow
1224  if( aNegative ^ bNegative )
1225  {
1226  // Result must be negative
1227  if( tmp <= (unsigned __int64)IntTraits< signed __int64 >::minInt )
1228  {
1229  ret = -(signed __int64)tmp;
1230  return SafeIntNoError;
1231  }
1232  }
1233  else
1234  {
1235  // Result must be positive
1236  if( tmp <= (unsigned __int64)IntTraits< signed __int64 >::maxInt )
1237  {
1238  ret = (signed __int64)tmp;
1239  return SafeIntNoError;
1240  }
1241  }
1242  }
1243 
1244  E::SafeIntOnOverflow();
1246  }
1247 };
1248 
1249 template < typename E > class LargeIntRegMultiply< signed __int32, signed __int64, E >
1250 {
1251 public:
1252  static SafeIntError RegMultiply( signed __int32 a, const signed __int64& b, signed __int32& ret )
1253  {
1254  bool aNegative = false;
1255  bool bNegative = false;
1256 
1257  unsigned __int32 tmp;
1258  __int64 b1 = b;
1259 
1260  if( a < 0 )
1261  {
1262  aNegative = true;
1263  a = -a;
1264  }
1265 
1266  if( b1 < 0 )
1267  {
1268  bNegative = true;
1269  b1 = -b1;
1270  }
1271 
1273  RegMultiply( (unsigned __int32)a, (unsigned __int64)b1, tmp ) == SafeIntNoError )
1274  {
1275  // The unsigned multiplication didn't overflow
1276  if( aNegative ^ bNegative )
1277  {
1278  // Result must be negative
1279  if( tmp <= (unsigned __int32)IntTraits< signed __int32 >::minInt )
1280  {
1281 #pragma warning(suppress:4146)
1282  ret = -tmp;
1283  return SafeIntNoError;
1284  }
1285  }
1286  else
1287  {
1288  // Result must be positive
1289  if( tmp <= (unsigned __int32)IntTraits< signed __int32 >::maxInt )
1290  {
1291  ret = (signed __int32)tmp;
1292  return SafeIntNoError;
1293  }
1294  }
1295  }
1296 
1297  E::SafeIntOnOverflow();
1299  }
1300 };
1301 
1302 template < typename E > class LargeIntRegMultiply< signed __int64, unsigned __int64, E >
1303 {
1304 public:
1305  static SafeIntError RegMultiply( const signed __int64& a, const unsigned __int64& b, signed __int64& ret )
1306  {
1307  bool aNegative = false;
1308 
1309  unsigned __int64 tmp;
1310  __int64 a1 = a;
1311 
1312  if( a1 < 0 )
1313  {
1314  aNegative = true;
1315  a1 = -a1;
1316  }
1317 
1319  RegMultiply( (unsigned __int64)a1, (unsigned __int64)b, tmp ) == SafeIntNoError )
1320  {
1321  // The unsigned multiplication didn't overflow
1322  if( aNegative )
1323  {
1324  // Result must be negative
1325  if( tmp <= (unsigned __int64)IntTraits< signed __int64 >::minInt )
1326  {
1327  ret = -((signed __int64)tmp);
1328  return SafeIntNoError;
1329  }
1330  }
1331  else
1332  {
1333  // Result must be positive
1334  if( tmp <= (unsigned __int64)IntTraits< signed __int64 >::maxInt )
1335  {
1336  ret = (signed __int64)tmp;
1337  return SafeIntNoError;
1338  }
1339  }
1340  }
1341 
1342  E::SafeIntOnOverflow();
1344  }
1345 };
1346 
1347 template < typename E > class MultiplicationHelper< unsigned __int64, unsigned __int64, E, MultiplicationState_Uint64Uint64 >
1348 {
1349 public:
1350  static SafeIntError Multiply( const unsigned __int64& t, const unsigned __int64& u, unsigned __int64& ret )
1351  {
1353  }
1354 };
1355 
1356 template < typename U, typename E > class MultiplicationHelper<unsigned __int64, U, E, MultiplicationState_Uint64Uint >
1357 {
1358 public:
1359  //U is any unsigned int 32-bit or less
1360  static SafeIntError Multiply( const unsigned __int64& t, const U& u, unsigned __int64& ret )
1361  {
1363  }
1364 };
1365 
1366 // converse of the previous function
1367 template < typename T, typename E > class MultiplicationHelper< T, unsigned __int64, E, MultiplicationState_UintUint64 >
1368 {
1369 public:
1370  // T is any unsigned int up to 32-bit
1371  static SafeIntError Multiply( const T& t, const unsigned __int64& u, T& ret )
1372  {
1373  unsigned __int32 tmp;
1374 
1377  {
1378  return SafeIntNoError;
1379  }
1380 
1381  E::SafeIntOnOverflow();
1383  }
1384 };
1385 
1386 template < typename U, typename E > class MultiplicationHelper< unsigned __int64, U, E, MultiplicationState_Uint64Int >
1387 {
1388 public:
1389  //U is any signed int, up to 64-bit
1390  static SafeIntError Multiply(const unsigned __int64& t, const U& u, unsigned __int64& ret)
1391  {
1393  }
1394 };
1395 
1396 template < typename E > class MultiplicationHelper<unsigned __int64, __int64, E, MultiplicationState_Uint64Int64 >
1397 {
1398 public:
1399  static SafeIntError Multiply(const unsigned __int64& t, const __int64& u, unsigned __int64& ret)
1400  {
1402  }
1403 };
1404 
1405 template < typename T, typename E > class MultiplicationHelper< T, __int64, E, MultiplicationState_UintInt64 >
1406 {
1407 public:
1408  //T is unsigned up to 32-bit
1409  static SafeIntError Multiply( const T& t, const __int64& u, T& ret )
1410  {
1411  unsigned __int32 tmp;
1412 
1415  {
1416  return SafeIntNoError;
1417  }
1418 
1419  E::SafeIntOnOverflow();
1421  }
1422 };
1423 
1424 template < typename U, typename E > class MultiplicationHelper<__int64, U, E, MultiplicationState_Int64Uint >
1425 {
1426 public:
1427  //U is unsigned up to 32-bit
1428  static SafeIntError Multiply( const __int64& t, const U& u, __int64& ret )
1429  {
1430  return LargeIntRegMultiply< __int64, unsigned __int32, E >::RegMultiply( t, (unsigned __int32)u, ret );
1431  }
1432 };
1433 
1434 template < typename E > class MultiplicationHelper<__int64, __int64, E, MultiplicationState_Int64Int64 >
1435 {
1436 public:
1437  static SafeIntError Multiply( const __int64& t, const __int64& u, __int64& ret )
1438  {
1440  }
1441 };
1442 
1443 template < typename U, typename E > class MultiplicationHelper<__int64, U, E, MultiplicationState_Int64Int>
1444 {
1445 public:
1446  //U is signed up to 32-bit
1447  static SafeIntError Multiply( const __int64& t, U u, __int64& ret )
1448  {
1449  return LargeIntRegMultiply< __int64, __int32, E >::RegMultiply( t, (__int32)u, ret );
1450  }
1451 };
1452 
1453 template < typename T, typename E > class MultiplicationHelper< T, unsigned __int64, E, MultiplicationState_IntUint64 >
1454 {
1455 public:
1456  //T is signed up to 32-bit
1457  static SafeIntError Multiply(T t, const unsigned __int64& u, T& ret)
1458  {
1459  __int32 tmp;
1460 
1463  {
1464  return SafeIntNoError;
1465  }
1466 
1467  E::SafeIntOnOverflow();
1469  }
1470 };
1471 
1472 template < typename E > class MultiplicationHelper<__int64, unsigned __int64, E, MultiplicationState_Int64Uint64>
1473 {
1474 public:
1475  //U is signed up to 32-bit
1476  static SafeIntError Multiply( const __int64& t, const unsigned __int64& u, __int64& ret )
1477  {
1479  }
1480 };
1481 
1482 template < typename T, typename E > class MultiplicationHelper< T, __int64, E, MultiplicationState_IntInt64>
1483 {
1484 public:
1485  //T is signed, up to 32-bit
1486  static SafeIntError Multiply( T t, const __int64& u, T& ret )
1487  {
1488  __int32 tmp;
1489 
1492  {
1493  return SafeIntNoError;
1494  }
1495 
1496  E::SafeIntOnOverflow();
1498  }
1499 };
1500 
1502 {
1509 };
1510 
1511 template < typename T, typename U > class DivisionMethod
1512 {
1513 public:
1514  enum
1515  {
1524  };
1525 };
1526 
1527 template < typename T, typename U, typename E, int Method = DivisionMethod< T, U >::method > class DivisionHelper;
1528 
1529 template < typename T, typename U, typename E > class DivisionHelper< T, U, E, DivisionState_OK >
1530 {
1531 public:
1532  static SafeIntError Divide( const T& t, const U& u, T& result )
1533  {
1534  if( u == 0 )
1535  {
1536  E::SafeIntOnDivZero();
1537  return SafeIntDivideByZero;
1538  }
1539 
1540  result = (T)( t/u );
1541  return SafeIntNoError;
1542  }
1543 };
1544 
1545 template < typename T, typename U, typename E > class DivisionHelper< T, U, E, DivisionState_UnsignedSigned>
1546 {
1547 public:
1548  static SafeIntError Divide( const T& t, const U& u, T& result )
1549  {
1550  if( u > 0 )
1551  {
1552  result = (T)( t/u );
1553  return SafeIntNoError;
1554  }
1555 
1556  if( u == 0 )
1557  {
1558  E::SafeIntOnDivZero();
1559  return SafeIntDivideByZero;
1560  }
1561 
1562  // it is always an error to try and divide an unsigned number by a negative signed number
1563  // unless u is bigger than t
1564  if( AbsValueHelper< U >::Abs( u ) > t )
1565  {
1566  result = 0;
1567  return SafeIntNoError;
1568  }
1569 
1570  E::SafeIntOnOverflow();
1572  }
1573 };
1574 
1575 template < typename T, typename U, typename E > class DivisionHelper< T, U, E, DivisionState_SignedUnsigned32 >
1576 {
1577 public:
1578  static SafeIntError Divide( const T& t, const U& u, T& result )
1579  {
1580  if( u == 0 )
1581  {
1582  E::SafeIntOnDivZero();
1583  return SafeIntDivideByZero;
1584  }
1585 
1586  // Test for t > 0
1587  // If t < 0, must explicitly upcast, or implicit upcast to ulong will cause errors
1588  // As it turns out, 32-bit division is about twice as fast, which justifies the extra conditional
1589  if( t > 0 )
1590  result = (T)( t/u );
1591  else
1592  result = (T)( (__int64)t/(__int64)u );
1593 
1594  return SafeIntNoError;
1595  }
1596 };
1597 
1598 template < typename T, typename E > class DivisionHelper< T, unsigned __int64, E, DivisionState_SignedUnsigned64 >
1599 {
1600 public:
1601  static SafeIntError Divide( const T& t, const unsigned __int64& u, T& result )
1602  {
1603  if( u == 0 )
1604  {
1605  E::SafeIntOnDivZero();
1606  return SafeIntDivideByZero;
1607  }
1608 
1609  if( u <= (unsigned __int64)IntTraits< T >::maxInt )
1610  {
1611  // Else u can safely be cast to T
1612 #pragma warning(suppress:4127)
1613  if( sizeof( T ) < sizeof( __int64 ) )
1614  result = (T)( (int)t/(int)u );
1615  else
1616  result = (T)((__int64)t/(__int64)u);
1617  }
1618  else // Corner case
1619  if( t == IntTraits< T >::minInt && u == (unsigned __int64)IntTraits< T >::minInt )
1620  {
1621  // Min int divided by it's own magnitude is -1
1622  result = -1;
1623  }
1624  else
1625  {
1626  result = 0;
1627  }
1628  return SafeIntNoError;
1629  }
1630 };
1631 
1632 template < typename T, typename U, typename E > class DivisionHelper< T, U, E, DivisionState_SignedUnsigned>
1633 {
1634 public:
1635  // T is any signed, U is unsigned and smaller than 32-bit
1636  // In this case, standard operator casting is correct
1637  static SafeIntError Divide( const T& t, const U& u, T& result )
1638  {
1639  if( u == 0 )
1640  {
1641  E::SafeIntOnDivZero();
1642  return SafeIntDivideByZero;
1643  }
1644 
1645  result = (T)( t/u );
1646  return SafeIntNoError;
1647  }
1648 };
1649 
1650 template < typename T, typename U, typename E > class DivisionHelper< T, U, E, DivisionState_SignedSigned>
1651 {
1652 public:
1653  static SafeIntError Divide( const T& t, const U& u, T& result )
1654  {
1655  if( u == 0 )
1656  {
1657  E::SafeIntOnDivZero();
1658  return SafeIntDivideByZero;
1659  }
1660 
1661  // Must test for corner case
1662  if( t == IntTraits< T >::minInt && u == -1 )
1663  {
1664  E::SafeIntOnOverflow();
1666  }
1667 
1668  result = (T)( t/u );
1669  return SafeIntNoError;
1670  }
1671 };
1672 
1674 {
1691 };
1692 
1693 template< typename T, typename U >
1695 {
1696 public:
1697  enum
1698  {
1699  //unsigned-unsigned
1705  //unsigned-signed
1712  //signed-signed
1719  //signed-unsigned
1727  };
1728 };
1729 
1730 template < typename T, typename U, typename E, int Method = AdditionMethod< T, U >::method > class AdditionHelper;
1731 
1732 template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastIntCheckMax >
1733 {
1734 public:
1735  static SafeIntError Addition( const T& lhs, const U& rhs, T& result )
1736  {
1737  //16-bit or less unsigned addition
1738  __int32 tmp = lhs + rhs;
1739 
1740  if( tmp <= (__int32)IntTraits< T >::maxInt )
1741  {
1742  result = (T)tmp;
1743  return SafeIntNoError;
1744  }
1745 
1746  E::SafeIntOnOverflow();
1748  }
1749 };
1750 
1751 template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastUintCheckOverflow >
1752 {
1753 public:
1754  static SafeIntError Addition( const T& lhs, const U& rhs, T& result )
1755  {
1756  // 32-bit or less - both are unsigned
1757  unsigned __int32 tmp = (unsigned __int32)lhs + (unsigned __int32)rhs;
1758 
1759  //we added didn't get smaller
1760  if( tmp >= lhs )
1761  {
1762  result = (T)tmp;
1763  return SafeIntNoError;
1764  }
1765  E::SafeIntOnOverflow();
1767  }
1768 };
1769 
1770 template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastUintCheckOverflowMax>
1771 {
1772 public:
1773  static SafeIntError Addition( const T& lhs, const U& rhs, T& result )
1774  {
1775  // 32-bit or less - both are unsigned
1776  unsigned __int32 tmp = (unsigned __int32)lhs + (unsigned __int32)rhs;
1777 
1778  // We added and it didn't get smaller or exceed maxInt
1779  if( tmp >= lhs && tmp <= IntTraits< T >::maxInt )
1780  {
1781  result = (T)tmp;
1782  return SafeIntNoError;
1783  }
1784  E::SafeIntOnOverflow();
1786  }
1787 };
1788 
1789 template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastUint64CheckOverflow>
1790 {
1791 public:
1792  static SafeIntError Addition( const T& lhs, const U& rhs, T& result )
1793  {
1794  // lhs unsigned __int64, rhs unsigned
1795  unsigned __int64 tmp = (unsigned __int64)lhs + (unsigned __int64)rhs;
1796 
1797  // We added and it didn't get smaller
1798  if(tmp >= lhs)
1799  {
1800  result = (T)tmp;
1801  return SafeIntNoError;
1802  }
1803 
1804  E::SafeIntOnOverflow();
1806  }
1807 };
1808 
1809 template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastUint64CheckOverflowMax >
1810 {
1811 public:
1812  static SafeIntError Addition( const T& lhs, const U& rhs, T& result )
1813  {
1814  //lhs unsigned __int64, rhs unsigned
1815  unsigned __int64 tmp = (unsigned __int64)lhs + (unsigned __int64)rhs;
1816 
1817  // We added and it didn't get smaller
1818  if( tmp >= lhs && tmp <= IntTraits< T >::maxInt )
1819  {
1820  result = (T)tmp;
1821  return SafeIntNoError;
1822  }
1823 
1824  E::SafeIntOnOverflow();
1826  }
1827 };
1828 
1829 template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastIntCheckMinMax >
1830 {
1831 public:
1832  static SafeIntError Addition( const T& lhs, const U& rhs, T& result )
1833  {
1834  // 16-bit or less - one or both are signed
1835  __int32 tmp = lhs + rhs;
1836 
1837  if( tmp <= (__int32)IntTraits< T >::maxInt && tmp >= (__int32)IntTraits< T >::minInt )
1838  {
1839  result = (T)tmp;
1840  return SafeIntNoError;
1841  }
1842 
1843  E::SafeIntOnOverflow();
1845  }
1846 };
1847 
1848 #pragma warning(push)
1849 #pragma warning(disable:4702)
1850 template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastInt64CheckMinMax >
1851 {
1852 public:
1853  static SafeIntError Addition( const T& lhs, const U& rhs, T& result )
1854  {
1855  // 32-bit or less - one or both are signed
1856  __int64 tmp = (__int64)lhs + (__int64)rhs;
1857 
1858  if( tmp <= (__int64)IntTraits< T >::maxInt && tmp >= (__int64)IntTraits< T >::minInt )
1859  {
1860  result = (T)tmp;
1861  return SafeIntNoError;
1862  }
1863 
1864  E::SafeIntOnOverflow();
1866  // return E::SafeIntOnOverflow2();
1867  }
1868 };
1869 #pragma warning(pop)
1870 
1871 template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastInt64CheckMax >
1872 {
1873 public:
1874  static SafeIntError Addition( const T& lhs, const U& rhs, T& result )
1875  {
1876  // 32-bit or less - lhs signed, rhs unsigned
1877  __int64 tmp = (__int64)lhs + (__int64)rhs;
1878 
1879  if( tmp <= IntTraits< T >::maxInt )
1880  {
1881  result = (T)tmp;
1882  return SafeIntNoError;
1883  }
1884 
1885  E::SafeIntOnOverflow();
1887  }
1888 };
1889 
1890 template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastUint64CheckMinMax >
1891 {
1892 public:
1893  static SafeIntError Addition( const T& lhs, const U& rhs, T& result )
1894  {
1895  // lhs is unsigned __int64, rhs signed
1896  unsigned __int64 tmp;
1897 
1898  if( rhs < 0 )
1899  {
1900  // So we're effectively subtracting
1901  tmp = AbsValueHelper< U >::Abs( rhs );
1902 
1903  if( tmp <= lhs )
1904  {
1905  result = lhs - tmp;
1906  return SafeIntNoError;
1907  }
1908  }
1909  else
1910  {
1911  // now we know that rhs can be safely cast into an unsigned __int64
1912  tmp = (unsigned __int64)lhs + (unsigned __int64)rhs;
1913 
1914  // We added and it did not become smaller
1915  if( tmp >= lhs )
1916  {
1917  result = (T)tmp;
1918  return SafeIntNoError;
1919  }
1920  }
1921 
1922  E::SafeIntOnOverflow();
1924  }
1925 };
1926 
1927 template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastUint64CheckMinMax2>
1928 {
1929 public:
1930  static SafeIntError Addition( const T& lhs, const U& rhs, T& result )
1931  {
1932  // lhs is unsigned and < 64-bit, rhs signed __int64
1933  if( rhs < 0 )
1934  {
1935  if( lhs >= (unsigned __int64)( -rhs ) )//negation is safe, since rhs is 64-bit
1936  {
1937  result = (T)( lhs + rhs );
1938  return SafeIntNoError;
1939  }
1940  }
1941  else
1942  {
1943  // now we know that rhs can be safely cast into an unsigned __int64
1944  unsigned __int64 tmp = (unsigned __int64)lhs + (unsigned __int64)rhs;
1945 
1946  // special case - rhs cannot be larger than 0x7fffffffffffffff, lhs cannot be larger than 0xffffffff
1947  // it is not possible for the operation above to overflow, so just check max
1948  if( tmp <= IntTraits< T >::maxInt )
1949  {
1950  result = (T)tmp;
1951  return SafeIntNoError;
1952  }
1953  }
1954  E::SafeIntOnOverflow();
1956  }
1957 };
1958 
1959 template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastInt64CheckOverflow>
1960 {
1961 public:
1962  static SafeIntError Addition( const T& lhs, const U& rhs, T& result )
1963  {
1964  // lhs is signed __int64, rhs signed
1965  __int64 tmp = (__int64)lhs + (__int64)rhs;
1966 
1967  if( lhs >= 0 )
1968  {
1969  // mixed sign cannot overflow
1970  if( rhs >= 0 && tmp < lhs )
1971  {
1972  E::SafeIntOnOverflow();
1974  }
1975  }
1976  else
1977  {
1978  // lhs negative
1979  if( rhs < 0 && tmp > lhs )
1980  {
1981  E::SafeIntOnOverflow();
1983  }
1984  }
1985 
1986  result = (T)tmp;
1987  return SafeIntNoError;
1988  }
1989 };
1990 
1991 template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastInt64CheckOverflowMinMax>
1992 {
1993 public:
1994  static SafeIntError Addition( const T& lhs, const U& rhs, T& result )
1995  {
1996  //rhs is signed __int64, lhs signed
1997  __int64 tmp;
1998 
2000  Addition( (__int64)lhs, (__int64)rhs, tmp ) == SafeIntNoError &&
2001  tmp <= IntTraits< T >::maxInt &&
2002  tmp >= IntTraits< T >::minInt )
2003  {
2004  result = (T)tmp;
2005  return SafeIntNoError;
2006  }
2007 
2008  E::SafeIntOnOverflow();
2010  }
2011 };
2012 
2013 template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_CastInt64CheckOverflowMax >
2014 {
2015 public:
2016  static SafeIntError Addition( const T& lhs, const U& rhs, T& result )
2017  {
2018  //lhs is signed __int64, rhs unsigned < 64-bit
2019  __int64 tmp = lhs + (__int64)rhs;
2020 
2021  if( tmp >= lhs )
2022  {
2023  result = (T)tmp;
2024  return SafeIntNoError;
2025  }
2026 
2027  E::SafeIntOnOverflow();
2029  }
2030 };
2031 
2032 template < typename E > class AdditionHelper < __int64, unsigned __int64, E, AdditionState_ManualCheckInt64Uint64 >
2033 {
2034 public:
2035  static SafeIntError Addition( const __int64& lhs, const unsigned __int64& rhs, __int64& result ) throw()
2036  {
2037  // rhs is unsigned __int64, lhs __int64
2038  __int64 tmp = lhs + (__int64)rhs;
2039 
2040  if( tmp >= lhs )
2041  {
2042  result = tmp;
2043  return SafeIntNoError;
2044  }
2045 
2046  E::SafeIntOnOverflow();
2048  }
2049 };
2050 
2051 template < typename T, typename U, typename E > class AdditionHelper < T, U, E, AdditionState_ManualCheck >
2052 {
2053 public:
2054  static SafeIntError Addition( const T& lhs, const U& rhs, T& result )
2055  {
2056  // rhs is unsigned __int64, lhs signed, 32-bit or less
2057 
2058  if( (unsigned __int32)( rhs >> 32 ) == 0 )
2059  {
2060  // Now it just happens to work out that the standard behavior does what we want
2061  // Adding explicit casts to show exactly what's happening here
2062  __int32 tmp = (__int32)( (unsigned __int32)rhs + (unsigned __int32)lhs );
2063 
2064  if( tmp >= lhs &&
2066  return SafeIntNoError;
2067  }
2068 
2069  E::SafeIntOnOverflow();
2071  }
2072 };
2073 
2075 {
2088  // states for SubtractionMethod2
2100 };
2101 
2102 template < typename T, typename U > class SubtractionMethod
2103 {
2104 public:
2105  enum
2106  {
2107  // unsigned-unsigned
2113  // unsigned-signed
2120  // signed-signed
2127  // signed-unsigned
2135  };
2136 };
2137 
2138 // this is for the case of U - SafeInt< T, E >
2139 template < typename T, typename U > class SubtractionMethod2
2140 {
2141 public:
2142  enum
2143  {
2144  // unsigned-unsigned
2150  // unsigned-signed
2157  // signed-signed
2164  // signed-unsigned
2172  };
2173 };
2174 
2175 template < typename T, typename U, typename E, int Method = SubtractionMethod< T, U >::method > class SubtractionHelper;
2176 
2177 template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_BothUnsigned >
2178 {
2179 public:
2180  static SafeIntError Subtract( const T& lhs, const U& rhs, T& result )
2181  {
2182  // both are unsigned - easy case
2183  if( rhs <= lhs )
2184  {
2185  result = (T)( lhs - rhs );
2186  return SafeIntNoError;
2187  }
2188 
2189  E::SafeIntOnOverflow();
2191  }
2192 };
2193 
2194 template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_BothUnsigned2 >
2195 {
2196 public:
2197  static SafeIntError Subtract( const T& lhs, const U& rhs, U& result )
2198  {
2199  // both are unsigned - easy case
2200  // Except we do have to check for overflow - lhs could be larger than result can hold
2201  if( rhs <= lhs )
2202  {
2203  T tmp = (T)(lhs - rhs);
2204  return SafeCastHelper< U, T, E>::Cast( tmp, result);
2205  }
2206 
2207  E::SafeIntOnOverflow();
2209  }
2210 };
2211 
2212 template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_CastIntCheckMinMax >
2213 {
2214 public:
2215  static SafeIntError Subtract( const T& lhs, const U& rhs, T& result )
2216  {
2217  // both values are 16-bit or less
2218  // rhs is signed, so could end up increasing or decreasing
2219  __int32 tmp = lhs - rhs;
2220 
2222  {
2223  result = (T)tmp;
2224  return SafeIntNoError;
2225  }
2226 
2227  E::SafeIntOnOverflow();
2229  }
2230 };
2231 
2232 template < typename U, typename T, typename E > class SubtractionHelper< U, T, E, SubtractionState_CastIntCheckMinMax2 >
2233 {
2234 public:
2235  static SafeIntError Subtract( const U& lhs, const T& rhs, T& result )
2236  {
2237  // both values are 16-bit or less
2238  // rhs is signed, so could end up increasing or decreasing
2239  __int32 tmp = lhs - rhs;
2240 
2241  return SafeCastHelper< T, __int32, E >::Cast( tmp, result );
2242  }
2243 };
2244 
2245 template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_CastIntCheckMin >
2246 {
2247 public:
2248  static SafeIntError Subtract( const T& lhs, const U& rhs, T& result )
2249  {
2250  // both values are 16-bit or less
2251  // rhs is unsigned - check only minimum
2252  __int32 tmp = lhs - rhs;
2253 
2254  if( tmp >= (__int32)IntTraits< T >::minInt )
2255  {
2256  result = (T)tmp;
2257  return SafeIntNoError;
2258  }
2259 
2260  E::SafeIntOnOverflow();
2262  }
2263 };
2264 
2265 template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_CastInt64CheckMinMax >
2266 {
2267 public:
2268  static SafeIntError Subtract( const T& lhs, const U& rhs, T& result )
2269  {
2270  // both values are 32-bit or less
2271  // rhs is signed, so could end up increasing or decreasing
2272  __int64 tmp = (__int64)lhs - (__int64)rhs;
2273 
2274  return SafeCastHelper< T, __int64, E >::Cast( tmp, result );
2275  }
2276 };
2277 
2278 template < typename U, typename T, typename E > class SubtractionHelper< U, T, E, SubtractionState_CastInt64CheckMinMax2 >
2279 {
2280 public:
2281  static SafeIntError Subtract( const U& lhs, const T& rhs, T& result )
2282  {
2283  // both values are 32-bit or less
2284  // rhs is signed, so could end up increasing or decreasing
2285  __int64 tmp = (__int64)lhs - (__int64)rhs;
2286 
2287  return SafeCastHelper< T, __int64, E >::Cast( tmp, result );
2288  }
2289 };
2290 
2291 template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_CastInt64CheckMin >
2292 {
2293 public:
2294  static SafeIntError Subtract( const T& lhs, const U& rhs, T& result )
2295  {
2296  // both values are 32-bit or less
2297  // rhs is unsigned - check only minimum
2298  __int64 tmp = (__int64)lhs - (__int64)rhs;
2299 
2300  if( tmp >= (__int64)IntTraits< T >::minInt )
2301  {
2302  result = (T)tmp;
2303  return SafeIntNoError;
2304  }
2305 
2306  E::SafeIntOnOverflow();
2308  }
2309 };
2310 
2311 template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_Uint64Int >
2312 {
2313 public:
2314  static SafeIntError Subtract( const T& lhs, const U& rhs, T& result )
2315  {
2316  // lhs is an unsigned __int64, rhs signed
2317  // must first see if rhs is positive or negative
2318  if( rhs >= 0 )
2319  {
2320  if( (unsigned __int64)rhs <= lhs )
2321  {
2322  result = (T)( lhs - (unsigned __int64)rhs );
2323  return SafeIntNoError;
2324  }
2325  }
2326  else
2327  {
2328  // we're now effectively adding
2329  T tmp = lhs + AbsValueHelper< U >::Abs( rhs );
2330 
2331  if(tmp >= lhs)
2332  {
2333  result = tmp;
2334  return SafeIntNoError;
2335  }
2336  }
2337 
2338  E::SafeIntOnOverflow();
2340  }
2341 };
2342 
2343 template < typename U, typename T, typename E > class SubtractionHelper< U, T, E, SubtractionState_Uint64Int2 >
2344 {
2345 public:
2346  static SafeIntError Subtract( const U& lhs, const T& rhs, T& result )
2347  {
2348  // U is unsigned __int64, T is signed
2349  if( rhs < 0 )
2350  {
2351  // treat this as addition
2352  unsigned __int64 tmp;
2353 
2354  tmp = lhs + (unsigned __int64)AbsValueHelper< T >::Abs( rhs );
2355 
2356  // must check for addition overflow and max
2357  if( tmp >= lhs && tmp <= IntTraits< T >::maxInt )
2358  {
2359  result = (T)tmp;
2360  return SafeIntNoError;
2361  }
2362  }
2363  else if( (unsigned __int64)rhs > lhs ) // now both are positive, so comparison always works
2364  {
2365  // result is negative
2366  // implies that lhs must fit into T, and result cannot overflow
2367  // Also allows us to drop to 32-bit math, which is faster on a 32-bit system
2368  result = (T)lhs - (T)rhs;
2369  return SafeIntNoError;
2370  }
2371  else
2372  {
2373  // result is positive
2374  unsigned __int64 tmp = (unsigned __int64)lhs - (unsigned __int64)rhs;
2375 
2376  if( tmp <= IntTraits< T >::maxInt )
2377  {
2378  result = (T)tmp;
2379  return SafeIntNoError;
2380  }
2381  }
2382 
2383  E::SafeIntOnOverflow();
2385  }
2386 };
2387 
2388 template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_UintInt64 >
2389 {
2390 public:
2391  static SafeIntError Subtract( const T& lhs, const U& rhs, T& result )
2392  {
2393  // lhs is an unsigned int32 or smaller, rhs signed __int64
2394  // must first see if rhs is positive or negative
2395  if( rhs >= 0 )
2396  {
2397  if( (unsigned __int64)rhs <= lhs )
2398  {
2399  result = (T)( lhs - (T)rhs );
2400  return SafeIntNoError;
2401  }
2402  }
2403  else
2404  {
2405  // we're now effectively adding
2406  // since lhs is 32-bit, and rhs cannot exceed 2^63
2407  // this addition cannot overflow
2408  unsigned __int64 tmp = lhs + (unsigned __int64)( -rhs ); // negation safe
2409 
2410  // but we could exceed MaxInt
2411  if(tmp <= IntTraits< T >::maxInt)
2412  {
2413  result = (T)tmp;
2414  return SafeIntNoError;
2415  }
2416  }
2417 
2418  E::SafeIntOnOverflow();
2420  }
2421 };
2422 
2423 template < typename U, typename T, typename E > class SubtractionHelper< U, T, E, SubtractionState_UintInt642 >
2424 {
2425 public:
2426  static SafeIntError Subtract( const U& lhs, const T& rhs, T& result )
2427  {
2428  // U unsigned 32-bit or less, T __int64
2429  if( rhs >= 0 )
2430  {
2431  // overflow not possible
2432  result = (T)( (__int64)lhs - rhs );
2433  return SafeIntNoError;
2434  }
2435  else
2436  {
2437  // we effectively have an addition
2438  // which cannot overflow internally
2439  unsigned __int64 tmp = (unsigned __int64)lhs + (unsigned __int64)( -rhs );
2440 
2441  if( tmp <= (unsigned __int64)IntTraits< T >::maxInt )
2442  {
2443  result = (T)tmp;
2444  return SafeIntNoError;
2445  }
2446  }
2447 
2448  E::SafeIntOnOverflow();
2450  }
2451 };
2452 
2453 template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_Int64Int >
2454 {
2455 public:
2456  static SafeIntError Subtract( const T& lhs, const U& rhs, T& result )
2457  {
2458  // lhs is an __int64, rhs signed (up to 64-bit)
2459  // we have essentially 4 cases:
2460  //
2461  // 1) lhs positive, rhs positive - overflow not possible
2462  // 2) lhs positive, rhs negative - equivalent to addition - result >= lhs or error
2463  // 3) lhs negative, rhs positive - check result <= lhs
2464  // 4) lhs negative, rhs negative - overflow not possible
2465 
2466  __int64 tmp = lhs - rhs;
2467 
2468  // Note - ideally, we can order these so that true conditionals
2469  // lead to success, which enables better pipelining
2470  // It isn't practical here
2471  if( ( lhs >= 0 && rhs < 0 && tmp < lhs ) || // condition 2
2472  ( rhs >= 0 && tmp > lhs ) ) // condition 3
2473  {
2474  E::SafeIntOnOverflow();
2476  }
2477 
2478  result = (T)tmp;
2479  return SafeIntNoError;
2480  }
2481 };
2482 
2483 template < typename U, typename T, typename E > class SubtractionHelper< U, T, E, SubtractionState_Int64Int2 >
2484 {
2485 public:
2486  static SafeIntError Subtract( const U& lhs, const T& rhs, T& result )
2487  {
2488  // lhs __int64, rhs any signed int (including __int64)
2489  __int64 tmp = lhs - rhs;
2490 
2491  // we have essentially 4 cases:
2492  //
2493  // 1) lhs positive, rhs positive - overflow not possible in tmp
2494  // 2) lhs positive, rhs negative - equivalent to addition - result >= lhs or error
2495  // 3) lhs negative, rhs positive - check result <= lhs
2496  // 4) lhs negative, rhs negative - overflow not possible in tmp
2497 
2498  if( lhs >= 0 )
2499  {
2500  // if both positive, overflow to negative not possible
2501  // which is why we'll explicitly check maxInt, and not call SafeCast
2502 #pragma warning(suppress:4127)
2504  ( rhs < 0 && tmp < lhs ) )
2505  {
2506  E::SafeIntOnOverflow();
2508  }
2509  }
2510  else
2511  {
2512  // lhs negative
2513 #pragma warning(suppress:4127)
2515  ( rhs >=0 && tmp > lhs ) )
2516  {
2517  E::SafeIntOnOverflow();
2519  }
2520  }
2521 
2522  result = (T)tmp;
2523  return SafeIntNoError;
2524  }
2525 };
2526 
2527 template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_IntInt64 >
2528 {
2529 public:
2530  static SafeIntError Subtract( const T& lhs, const U& rhs, T& result )
2531  {
2532  // lhs is a 32-bit int or less, rhs __int64
2533  // we have essentially 4 cases:
2534  //
2535  // lhs positive, rhs positive - rhs could be larger than lhs can represent
2536  // lhs positive, rhs negative - additive case - check tmp >= lhs and tmp > max int
2537  // lhs negative, rhs positive - check tmp <= lhs and tmp < min int
2538  // lhs negative, rhs negative - addition cannot internally overflow, check against max
2539 
2540  __int64 tmp = (__int64)lhs - rhs;
2541 
2542  if( lhs >= 0 )
2543  {
2544  // first case
2545  if( rhs >= 0 )
2546  {
2547  if( tmp >= IntTraits< T >::minInt )
2548  {
2549  result = (T)tmp;
2550  return SafeIntNoError;
2551  }
2552  }
2553  else
2554  {
2555  // second case
2556  if( tmp >= lhs && tmp <= IntTraits< T >::maxInt )
2557  {
2558  result = (T)tmp;
2559  return SafeIntNoError;
2560  }
2561  }
2562  }
2563  else
2564  {
2565  // lhs < 0
2566  // third case
2567  if( rhs >= 0 )
2568  {
2569  if( tmp <= lhs && tmp >= IntTraits< T >::minInt )
2570  {
2571  result = (T)tmp;
2572  return SafeIntNoError;
2573  }
2574  }
2575  else
2576  {
2577  // fourth case
2578  if( tmp <= IntTraits< T >::maxInt )
2579  {
2580  result = (T)tmp;
2581  return SafeIntNoError;
2582  }
2583  }
2584  }
2585 
2586  E::SafeIntOnOverflow();
2588  }
2589 };
2590 
2591 template < typename U, typename T, typename E > class SubtractionHelper< U, T, E, SubtractionState_IntInt642 >
2592 {
2593 public:
2594  static SafeIntError Subtract( const U& lhs, const T& rhs, T& result )
2595  {
2596  // lhs is any signed int32 or smaller, rhs is int64
2597  __int64 tmp = (__int64)lhs - rhs;
2598 
2599  if( ( lhs >= 0 && rhs < 0 && tmp < lhs ) ||
2600  ( rhs > 0 && tmp > lhs ) )
2601  {
2602  E::SafeIntOnOverflow();
2604  //else OK
2605  }
2606 
2607  result = (T)tmp;
2608  return SafeIntNoError;
2609  }
2610 };
2611 
2612 template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_Int64Uint >
2613 {
2614 public:
2615  static SafeIntError Subtract( const T& lhs, const U& rhs, T& result )
2616  {
2617  // lhs is a 64-bit int, rhs unsigned int32 or smaller
2618 
2619  __int64 tmp = lhs - (__int64)rhs;
2620 
2621  if( tmp <= lhs )
2622  {
2623  result = (T)tmp;
2624  return SafeIntNoError;
2625  }
2626 
2627  E::SafeIntOnOverflow();
2629  }
2630 };
2631 
2632 template < typename U, typename T, typename E > class SubtractionHelper< U, T, E, SubtractionState_Int64Uint2 >
2633 {
2634 public:
2635  // lhs is __int64, rhs is unsigned 32-bit or smaller
2636  static SafeIntError Subtract( const U& lhs, const T& rhs, T& result )
2637  {
2638  __int64 tmp = lhs - (__int64)rhs;
2639 
2640  if( tmp <= IntTraits< T >::maxInt && tmp >= IntTraits< T >::minInt )
2641  {
2642  result = (T)tmp;
2643  return SafeIntNoError;
2644  }
2645 
2646  E::SafeIntOnOverflow();
2648  }
2649 };
2650 
2651 template < typename T, typename U, typename E > class SubtractionHelper< T, U, E, SubtractionState_IntUint64 >
2652 {
2653 public:
2654  static SafeIntError Subtract( const T& lhs, const U& rhs, T& result )
2655  {
2656  // lhs is any signed int, rhs unsigned int64
2657  // check against available range
2658 
2659  // We need the absolute value of IntTraits< T >::minInt
2660  // This will give it to us without extraneous compiler warnings
2661  const unsigned __int64 AbsMinIntT = (unsigned __int64)IntTraits< T >::maxInt + 1;
2662 
2663  if( lhs < 0 )
2664  {
2665  if( rhs <= AbsMinIntT - AbsValueHelper< T >::Abs( lhs ) )
2666  {
2667  result = (T)( lhs - rhs );
2668  return SafeIntNoError;
2669  }
2670  }
2671  else
2672  {
2673  if( rhs <= AbsMinIntT + (unsigned __int64)lhs )
2674  {
2675  result = (T)( lhs - rhs );
2676  return SafeIntNoError;
2677  }
2678  }
2679 
2680  E::SafeIntOnOverflow();
2682  }
2683 };
2684 
2685 template < typename U, typename T, typename E > class SubtractionHelper< U, T, E, SubtractionState_IntUint642 >
2686 {
2687 public:
2688  static SafeIntError Subtract( const U& lhs, const T& rhs, T& result )
2689  {
2690  // We run into upcasting problems on comparison - needs 2 checks
2691  if( lhs >= 0 && (T)lhs >= rhs )
2692  {
2693  result = (T)((U)lhs - (U)rhs);
2694  return SafeIntNoError;
2695  }
2696 
2697  E::SafeIntOnOverflow();
2699  }
2700 };
2701 
2702 template < typename E > class SubtractionHelper< __int64, unsigned __int64, E, SubtractionState_Int64Uint64 >
2703 {
2704 public:
2705  static SafeIntError Subtract( const __int64& lhs, const unsigned __int64& rhs, __int64& result )
2706  {
2707  // if we subtract, and it gets larger, there's a problem
2708  __int64 tmp = lhs - (__int64)rhs;
2709 
2710  if( tmp <= lhs )
2711  {
2712  result = tmp;
2713  return SafeIntNoError;
2714  }
2715  E::SafeIntOnOverflow();
2717  }
2718 };
2719 
2720 template < typename E > class SubtractionHelper< __int64, unsigned __int64, E, SubtractionState_Int64Uint642 >
2721 {
2722 public:
2723  // If lhs is negative, immediate problem - return must be positive, and subtracting only makes it
2724  // get smaller. If rhs > lhs, then it would also go negative, which is the other case
2725  static SafeIntError Subtract( const __int64& lhs, const unsigned __int64& rhs, unsigned __int64& result )
2726  {
2727  if( lhs >= 0 && (unsigned __int64)lhs >= rhs )
2728  {
2729  result = (unsigned __int64)lhs - rhs;
2730  return SafeIntNoError;
2731  }
2732 
2733  E::SafeIntOnOverflow();
2735  }
2736 };
2737 
2739 {
2744 };
2745 
2746 template < typename T, typename U > class BinaryMethod
2747 {
2748 public:
2749  enum
2750  {
2751  // If both operands are unsigned OR
2752  // return type is smaller than rhs OR
2753  // return type is larger and rhs is unsigned
2754  // Then binary operations won't produce unexpected results
2755  method = ( sizeof( T ) <= sizeof( U ) ||
2761  };
2762 };
2763 
2764 template < typename T, typename U, int Method = BinaryMethod< T, U >::method > class BinaryAndHelper;
2765 
2766 template < typename T, typename U > class BinaryAndHelper< T, U, BinaryState_OK >
2767 {
2768 public:
2769  static T And( T lhs, U rhs ){ return (T)( lhs & rhs ); }
2770 };
2771 
2772 template < typename T, typename U > class BinaryAndHelper< T, U, BinaryState_Int8 >
2773 {
2774 public:
2775  static T And( T lhs, U rhs )
2776  {
2777  // cast forces sign extension to be zeros
2778  _SAFEINT_BINARY_ASSERT( ( lhs & rhs ) == ( lhs & (unsigned __int8)rhs ) );
2779  return (T)( lhs & (unsigned __int8)rhs );
2780  }
2781 };
2782 
2783 template < typename T, typename U > class BinaryAndHelper< T, U, BinaryState_Int16 >
2784 {
2785 public:
2786  static T And( T lhs, U rhs )
2787  {
2788  //cast forces sign extension to be zeros
2789  _SAFEINT_BINARY_ASSERT( ( lhs & rhs ) == ( lhs & (unsigned __int16)rhs ) );
2790  return (T)( lhs & (unsigned __int16)rhs );
2791  }
2792 };
2793 
2794 template < typename T, typename U > class BinaryAndHelper< T, U, BinaryState_Int32 >
2795 {
2796 public:
2797  static T And( T lhs, U rhs )
2798  {
2799  //cast forces sign extension to be zeros
2800  _SAFEINT_BINARY_ASSERT( ( lhs & rhs ) == ( lhs & (unsigned __int32)rhs ) );
2801  return (T)( lhs & (unsigned __int32)rhs );
2802  }
2803 };
2804 
2805 template < typename T, typename U, int Method = BinaryMethod< T, U >::method > class BinaryOrHelper;
2806 
2807 template < typename T, typename U > class BinaryOrHelper< T, U, BinaryState_OK >
2808 {
2809 public:
2810  static T Or( T lhs, U rhs ){ return (T)( lhs | rhs ); }
2811 };
2812 
2813 template < typename T, typename U > class BinaryOrHelper< T, U, BinaryState_Int8 >
2814 {
2815 public:
2816  static T Or( T lhs, U rhs )
2817  {
2818  //cast forces sign extension to be zeros
2819  _SAFEINT_BINARY_ASSERT( ( lhs | rhs ) == ( lhs | (unsigned __int8)rhs ) );
2820  return (T)( lhs | (unsigned __int8)rhs );
2821  }
2822 };
2823 
2824 template < typename T, typename U > class BinaryOrHelper< T, U, BinaryState_Int16 >
2825 {
2826 public:
2827  static T Or( T lhs, U rhs )
2828  {
2829  //cast forces sign extension to be zeros
2830  _SAFEINT_BINARY_ASSERT( ( lhs | rhs ) == ( lhs | (unsigned __int16)rhs ) );
2831  return (T)( lhs | (unsigned __int16)rhs );
2832  }
2833 };
2834 
2835 template < typename T, typename U > class BinaryOrHelper< T, U, BinaryState_Int32 >
2836 {
2837 public:
2838  static T Or( T lhs, U rhs )
2839  {
2840  //cast forces sign extension to be zeros
2841  _SAFEINT_BINARY_ASSERT( ( lhs | rhs ) == ( lhs | (unsigned __int32)rhs ) );
2842  return (T)( lhs | (unsigned __int32)rhs );
2843  }
2844 };
2845 
2846 template <typename T, typename U, int Method = BinaryMethod< T, U >::method > class BinaryXorHelper;
2847 
2848 template < typename T, typename U > class BinaryXorHelper< T, U, BinaryState_OK >
2849 {
2850 public:
2851  static T Xor( T lhs, U rhs ){ return (T)( lhs ^ rhs ); }
2852 };
2853 
2854 template < typename T, typename U > class BinaryXorHelper< T, U, BinaryState_Int8 >
2855 {
2856 public:
2857  static T Xor( T lhs, U rhs )
2858  {
2859  // cast forces sign extension to be zeros
2860  _SAFEINT_BINARY_ASSERT( ( lhs ^ rhs ) == ( lhs ^ (unsigned __int8)rhs ) );
2861  return (T)( lhs ^ (unsigned __int8)rhs );
2862  }
2863 };
2864 
2865 template < typename T, typename U > class BinaryXorHelper< T, U, BinaryState_Int16 >
2866 {
2867 public:
2868  static T Xor( T lhs, U rhs )
2869  {
2870  // cast forces sign extension to be zeros
2871  _SAFEINT_BINARY_ASSERT( ( lhs ^ rhs ) == ( lhs ^ (unsigned __int16)rhs ) );
2872  return (T)( lhs ^ (unsigned __int16)rhs );
2873  }
2874 };
2875 
2876 template < typename T, typename U > class BinaryXorHelper< T, U, BinaryState_Int32 >
2877 {
2878 public:
2879  static T Xor( T lhs, U rhs )
2880  {
2881  // cast forces sign extension to be zeros
2882  _SAFEINT_BINARY_ASSERT( ( lhs ^ rhs ) == ( lhs ^ (unsigned __int32)rhs ) );
2883  return (T)( lhs ^ (unsigned __int32)rhs );
2884  }
2885 };
2886 
2887 #pragma warning(pop)
2888 } // namespace details
2889 
2890 } // namespace utilities
2891 
2892 } // namespace msl
2893 
2894 #pragma pack(pop)
AdditionState
Definition: safeint_internal.h:1673
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:2268
static T And(T lhs, U rhs)
Definition: safeint_internal.h:2786
static SafeIntError Modulus(const T &t, const U &u, T &result)
Definition: safeint_internal.h:640
static unsigned __int64 Abs(T t)
Definition: safeint_internal.h:226
static const T maxInt
Definition: safeint_internal.h:83
Definition: safeint_internal.h:1690
static SafeIntError Subtract(const U &lhs, const T &rhs, T &result)
Definition: safeint_internal.h:2426
static bool GreaterThan(const T t, const U u)
Definition: safeint_internal.h:544
static SafeIntError Cast(U u, T &t)
Definition: safeint_internal.h:398
static T Abs(T t)
Definition: safeint_internal.h:236
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:2294
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:1962
Definition: safeint_internal.h:2096
Definition: safeint_internal.h:776
Definition: safeint_internal.h:581
Definition: safeint_internal.h:201
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:1874
Definition: safeint_internal.h:1689
Definition: safeint_internal.h:1503
DivisionState
Definition: safeint_internal.h:1501
Definition: safeint.h:255
Definition: safeint_internal.h:283
static SafeIntError Negative(T t, T &ret)
Definition: safeint_internal.h:267
static SafeIntError Cast(bool b, T &t)
Definition: safeint_internal.h:362
static SafeIntError Subtract(const U &lhs, const T &rhs, T &result)
Definition: safeint_internal.h:2688
Definition: safeint_internal.h:2085
Definition: safeint_internal.h:527
Definition: safeint_internal.h:2099
static SafeIntError Divide(const T &t, const U &u, T &result)
Definition: safeint_internal.h:1578
Definition: safeint_internal.h:51
Definition: safeint_internal.h:211
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:1994
Definition: safeint_internal.h:1508
Definition: safeint_internal.h:2092
static SafeIntError Modulus(const T &t, const U &u, T &result)
Definition: safeint_internal.h:613
Definition: safeint_internal.h:206
static T Or(T lhs, U rhs)
Definition: safeint_internal.h:2810
_CRTIMP _In_opt_z_ const wchar_t _In_opt_z_ const wchar_t unsigned int
Definition: crtdefs.h:642
Definition: safeint_internal.h:475
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:1792
static bool IsEquals(const T t, const U u)
Definition: safeint_internal.h:514
Definition: safeint_internal.h:54
Definition: safeint_internal.h:195
Definition: safeint_internal.h:738
static SafeIntError Cast(U u, T &t)
Definition: safeint_internal.h:344
Definition: safeint_internal.h:456
static SafeIntError Modulus(const T &t, const U &u, T &result)
Definition: safeint_internal.h:586
Definition: safeint_internal.h:2081
static SafeIntError RegMultiply(const unsigned __int64 &a, unsigned __int32 b, unsigned __int64 &ret)
Definition: safeint_internal.h:928
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:2314
Definition: safeint_internal.h:63
static T Xor(T lhs, U rhs)
Definition: safeint_internal.h:2857
static SafeIntError Multiply(const T &t, const U &u, T &ret)
Definition: safeint_internal.h:801
Definition: safeint_internal.h:289
static SafeIntError Cast(U u, T &t)
Definition: safeint_internal.h:431
Definition: safeint_internal.h:299
static SafeIntError Subtract(const __int64 &lhs, const unsigned __int64 &rhs, __int64 &result)
Definition: safeint_internal.h:2705
Definition: safeint_internal.h:2086
static bool GreaterThan(const T t, const U u)
Definition: safeint_internal.h:532
Definition: safeint_internal.h:70
Definition: safeint_internal.h:74
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:1853
static SafeIntError Cast(T t, bool &b)
Definition: safeint_internal.h:372
Definition: safeint_internal.h:67
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:2615
static T Or(T lhs, U rhs)
Definition: safeint_internal.h:2827
Definition: safeint_internal.h:71
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:1754
static bool GreaterThan(const T t, const U u)
Definition: safeint_internal.h:550
static SafeIntError RegMultiply(const unsigned __int64 &a, const unsigned __int64 &b, unsigned __int64 &ret)
Definition: safeint_internal.h:861
Definition: safeint_internal.h:734
static T Xor(T lhs, U rhs)
Definition: safeint_internal.h:2879
Definition: safeint_internal.h:2742
static SafeIntError Subtract(const T &lhs, const U &rhs, U &result)
Definition: safeint_internal.h:2197
static SafeIntError RegMultiply(const signed __int64 &a, const signed __int64 &b, signed __int64 &ret)
Definition: safeint_internal.h:1103
Definition: safeint_internal.h:68
MultiplicationState
Definition: safeint_internal.h:716
Definition: safeint_internal.h:2740
static SafeIntError Subtract(const U &lhs, const T &rhs, T &result)
Definition: safeint_internal.h:2281
static SafeIntError Multiply(const unsigned __int64 &t, const U &u, unsigned __int64 &ret)
Definition: safeint_internal.h:1360
static T And(T lhs, U rhs)
Definition: safeint_internal.h:2775
static SafeIntError Multiply(const T &t, const U &u, T &ret)
Definition: safeint_internal.h:820
#define _ASSERTE(expr)
Definition: crtdbg.h:216
static SafeIntError Divide(const T &t, const U &u, T &result)
Definition: safeint_internal.h:1637
static SafeIntError Multiply(const __int64 &t, const __int64 &u, __int64 &ret)
Definition: safeint_internal.h:1437
Definition: safeint.h:265
Definition: safeint_internal.h:108
Definition: safeint_internal.h:450
unsigned short wchar_t
Definition: crtdefs.h:536
static T Or(T lhs, U rhs)
Definition: safeint_internal.h:2816
Definition: safeint_internal.h:2082
Definition: safeint_internal.h:2764
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:1735
Definition: safeint_internal.h:196
static SafeIntError RegMultiply(const unsigned __int64 &a, signed __int64 b, unsigned __int64 &ret)
Definition: safeint_internal.h:989
static SafeIntError Multiply(const T &t, const U &u, T &ret)
Definition: safeint_internal.h:839
static void SafeIntOnDivZero()
Definition: safeint_internal.h:95
Definition: safeint_internal.h:2097
static bool IsEquals(const T t, const U u)
Definition: safeint_internal.h:492
Definition: safeint_internal.h:285
#define bool
Definition: stdbool.h:10
Definition: safeint_internal.h:2093
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:1832
Definition: safeint_internal.h:2741
static SafeIntError Divide(const T &t, const unsigned __int64 &u, T &result)
Definition: safeint_internal.h:1601
Definition: safeint_internal.h:100
static bool IsEquals(const T t, const U u)
Definition: safeint_internal.h:480
Definition: safeint_internal.h:449
static bool IsEquals(const T t, const U u)
Definition: safeint_internal.h:486
Definition: safeint_internal.h:76
static SafeIntError Subtract(const U &lhs, const T &rhs, T &result)
Definition: safeint_internal.h:2486
static T Xor(T lhs, U rhs)
Definition: safeint_internal.h:2851
Definition: safeint_internal.h:464
static SafeIntError RegMultiply(const unsigned __int64 &a, signed __int32 b, unsigned __int64 &ret)
Definition: safeint_internal.h:974
static unsigned __int32 Abs(T t)
Definition: safeint_internal.h:216
Definition: safeint_internal.h:1511
static SafeIntError Multiply(const T &t, const __int64 &u, T &ret)
Definition: safeint_internal.h:1409
#define false
Definition: stdbool.h:11
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:2054
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:2391
Definition: safeint_internal.h:78
Definition: safeint_internal.h:294
Definition: safeint_internal.h:288
static SafeIntError Addition(const __int64 &lhs, const unsigned __int64 &rhs, __int64 &result)
Definition: safeint_internal.h:2035
static SafeIntError Multiply(const unsigned __int64 &t, const __int64 &u, unsigned __int64 &ret)
Definition: safeint_internal.h:1399
Definition: safeint_internal.h:66
static T And(T lhs, U rhs)
Definition: safeint_internal.h:2769
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:2215
Definition: safeint_internal.h:1527
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:2180
BinaryState
Definition: safeint_internal.h:2738
_STATIC_ASSERT(NumericType< T >::isInt||NumericType< T >::isBool)
static SafeIntError Modulus(const T &t, const U &u, T &result)
Definition: safeint_internal.h:666
static SafeIntError Subtract(const __int64 &lhs, const unsigned __int64 &rhs, unsigned __int64 &result)
Definition: safeint_internal.h:2725
SafeIntError
Definition: safeint.h:261
Definition: safeint_internal.h:290
Definition: safeint_internal.h:1730
static SafeIntError Divide(const T &t, const U &u, T &result)
Definition: safeint_internal.h:1548
Definition: safeint_internal.h:72
Definition: safeint_internal.h:69
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:2654
Definition: safeint_internal.h:287
static SafeIntError Negative(T t, T &ret)
Definition: safeint_internal.h:249
static SafeIntError RegMultiply(signed __int32 a, const unsigned __int64 &b, signed __int32 &ret)
Definition: safeint_internal.h:1004
static T And(T lhs, U rhs)
Definition: safeint_internal.h:2797
static void SafeIntOnOverflow()
Definition: safeint_internal.h:91
Definition: safeint_internal.h:2084
static SafeIntError Modulus(const T &t, const U &u, T &result)
Definition: safeint_internal.h:693
Definition: safeint_internal.h:2094
static const T minInt
Definition: safeint_internal.h:84
Definition: safeint.h:263
Definition: safeint_internal.h:451
static bool IsEquals(const T t, const U u)
Definition: safeint_internal.h:498
Definition: safeint_internal.h:157
AbsMethod
Definition: safeint_internal.h:193
Definition: safeint_internal.h:2139
Definition: safeint_internal.h:856
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:1930
static bool GreaterThan(const T t, const U u)
Definition: safeint_internal.h:538
static SafeIntError Cast(U u, T &t)
Definition: safeint_internal.h:382
Definition: safeint_internal.h:64
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:1812
static SafeIntError Multiply(const __int64 &t, U u, __int64 &ret)
Definition: safeint_internal.h:1447
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:1893
static SafeIntError RegMultiply(const signed __int64 &a, const unsigned __int64 &b, signed __int64 &ret)
Definition: safeint_internal.h:1305
Definition: safeint_internal.h:2805
static SafeIntError Divide(const T &t, const U &u, T &result)
Definition: safeint_internal.h:1532
Definition: safeint_internal.h:452
Definition: safeint_internal.h:30
static bool GreaterThan(const T t, const U u)
Definition: safeint_internal.h:566
Definition: safeint_internal.h:61
static SafeIntError RegMultiply(const signed __int64 &a, signed __int32 b, signed __int64 &ret)
Definition: safeint_internal.h:1199
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:2248
static SafeIntError Subtract(const U &lhs, const T &rhs, T &result)
Definition: safeint_internal.h:2594
Definition: safeint_internal.h:73
static SafeIntError Multiply(const __int64 &t, const U &u, __int64 &ret)
Definition: safeint_internal.h:1428
static SafeIntError Cast(U u, T &t)
Definition: safeint_internal.h:332
Definition: safeint_internal.h:1694
static SafeIntError RegMultiply(const signed __int64 &a, unsigned __int32 b, signed __int64 &ret)
Definition: safeint_internal.h:1156
Definition: safeint_internal.h:65
Definition: safeint_internal.h:2746
Definition: safeint_internal.h:62
static SafeIntError Subtract(const U &lhs, const T &rhs, T &result)
Definition: safeint_internal.h:2235
static SafeIntError RegMultiply(unsigned __int32 a, const unsigned __int64 &b, unsigned __int32 &ret)
Definition: safeint_internal.h:1058
Definition: safeint_internal.h:327
Definition: safeint_internal.h:51
static SafeIntError Subtract(const U &lhs, const T &rhs, T &result)
Definition: safeint_internal.h:2346
static SafeIntError RegMultiply(signed __int32 a, const signed __int64 &b, signed __int32 &ret)
Definition: safeint_internal.h:1252
Definition: safeint_internal.h:197
static SafeIntError Multiply(const T &t, const U &u, T &ret)
Definition: safeint_internal.h:782
ComparisonMethod
Definition: safeint_internal.h:446
Definition: safeint_internal.h:244
Definition: safeint_internal.h:284
static SafeIntError Multiply(T t, const __int64 &u, T &ret)
Definition: safeint_internal.h:1486
static SafeIntError Multiply(const unsigned __int64 &t, const unsigned __int64 &u, unsigned __int64 &ret)
Definition: safeint_internal.h:1350
static SafeIntError Multiply(const unsigned __int64 &t, const U &u, unsigned __int64 &ret)
Definition: safeint_internal.h:1390
Definition: safeint_internal.h:2175
static SafeIntError Divide(const T &t, const U &u, T &result)
Definition: safeint_internal.h:1653
SubtractionState
Definition: safeint_internal.h:2074
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:1773
Definition: safeint_internal.h:75
static SafeIntError Subtract(const U &lhs, const T &rhs, T &result)
Definition: safeint_internal.h:2636
Definition: safeint_internal.h:286
static SafeIntError Multiply(T t, const unsigned __int64 &u, T &ret)
Definition: safeint_internal.h:1457
static SafeIntError Cast(U u, T &t)
Definition: safeint_internal.h:414
Definition: safeint_internal.h:2083
#define true
Definition: stdbool.h:12
Definition: safeint_internal.h:2743
static SafeIntError Addition(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:2016
static SafeIntError Multiply(const __int64 &t, const unsigned __int64 &u, __int64 &ret)
Definition: safeint_internal.h:1476
static T Or(T lhs, U rhs)
Definition: safeint_internal.h:2838
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:2530
CastMethod
Definition: safeint_internal.h:281
Definition: safeint_internal.h:2102
static T Xor(T lhs, U rhs)
Definition: safeint_internal.h:2868
Definition: safeint_internal.h:51
#define _SAFEINT_UNSIGNED_NEGATION_BEHAVIOR()
Definition: safeint.h:244
Definition: safeint_internal.h:2095
static SafeIntError Subtract(const T &lhs, const U &rhs, T &result)
Definition: safeint_internal.h:2456
static SafeIntError Multiply(const T &t, const unsigned __int64 &u, T &ret)
Definition: safeint_internal.h:1371
Definition: safeint_internal.h:448
Definition: safeint_internal.h:2846
static SafeIntError RegMultiply(unsigned __int32 a, const signed __int64 &b, unsigned __int32 &ret)
Definition: safeint_internal.h:1088
#define _SAFEINT_BINARY_ASSERT(x)
Definition: safeint.h:233