MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
misc.hpp
1 /*
2  Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; see the file COPYING. If not, write to the
15  Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
16  MA 02110-1301 USA.
17 */
18 
19 /* based on Wei Dai's misc.h from CryptoPP */
20 
21 #ifndef TAO_CRYPT_MISC_HPP
22 #define TAO_CRYPT_MISC_HPP
23 
24 
25 #if !defined(DO_TAOCRYPT_KERNEL_MODE)
26  #include <stdlib.h>
27  #include <string.h>
28 #else
29  #include "kernelc.hpp"
30 #endif
31 
32 #include "types.hpp"
33 #include "type_traits.hpp"
34 
35 
36 
37 namespace TaoCrypt {
38 
39 
40 // Delete static singleton holders
41 void CleanUp();
42 
43 
44 #ifdef YASSL_PURE_C
45 
46  // library allocation
47  struct new_t {}; // TaoCrypt New type
48  extern new_t tc; // pass in parameter
49 
50  } // namespace TaoCrypt
51 
52  void* operator new (size_t, TaoCrypt::new_t);
53  void* operator new[](size_t, TaoCrypt::new_t);
54 
55  void operator delete (void*, TaoCrypt::new_t);
56  void operator delete[](void*, TaoCrypt::new_t);
57 
58 
59  namespace TaoCrypt {
60 
61  template<typename T>
62  void tcDelete(T* ptr)
63  {
64  if (ptr) ptr->~T();
65  ::operator delete(ptr, TaoCrypt::tc);
66  }
67 
68  template<typename T>
69  void tcArrayDelete(T* ptr)
70  {
71  // can't do array placement destruction since not tracking size in
72  // allocation, only allow builtins to use array placement since they
73  // don't need destructors called
74  typedef char builtin[IsFundamentalType<T>::Yes ? 1 : -1];
75  (void)sizeof(builtin);
76 
77  ::operator delete[](ptr, TaoCrypt::tc);
78  }
79 
80  #define NEW_TC new (TaoCrypt::tc)
81 
82 
83  // to resolve compiler generated operator delete on base classes with
84  // virtual destructors (when on stack)
85  class virtual_base {
86  public:
87  static void operator delete(void*) { }
88  };
89 
90 #else // YASSL_PURE_C
91 
92 
93  template<typename T>
94  void tcDelete(T* ptr)
95  {
96  delete ptr;
97  }
98 
99  template<typename T>
100  void tcArrayDelete(T* ptr)
101  {
102  delete[] ptr;
103  }
104 
105  #define NEW_TC new
106 
107  class virtual_base {};
108 
109 
110 #endif // YASSL_PURE_C
111 
112 
113 #if defined(_MSC_VER) || defined(__BCPLUSPLUS__)
114  #define INTEL_INTRINSICS
115  #define FAST_ROTATE
116 #elif defined(__MWERKS__) && TARGET_CPU_PPC
117  #define PPC_INTRINSICS
118  #define FAST_ROTATE
119 #elif defined(__GNUC__) && defined(__i386__)
120  // GCC does peephole optimizations which should result in using rotate
121  // instructions
122  #define FAST_ROTATE
123 #endif
124 
125 
126 // no gas on these systems ?, disable for now
127 #if defined(__sun__) || defined (__APPLE__)
128  #define TAOCRYPT_DISABLE_X86ASM
129 #endif
130 
131 // icc problem with -03 and integer, disable for now
132 #if defined(__INTEL_COMPILER)
133  #define TAOCRYPT_DISABLE_X86ASM
134 #endif
135 
136 
137 // Turn on ia32 ASM for Big Integer
138 // CodeWarrior defines _MSC_VER
139 #if !defined(TAOCRYPT_DISABLE_X86ASM) && ((defined(_MSC_VER) && \
140  !defined(__MWERKS__) && defined(_M_IX86)) || \
141  (defined(__GNUC__) && defined(__i386__)))
142  #define TAOCRYPT_X86ASM_AVAILABLE
143 #endif
144 
145 
146 #ifdef TAOCRYPT_X86ASM_AVAILABLE
147  bool HaveCpuId();
148  bool IsPentium();
149  void CpuId(word32 input, word32 *output);
150 
151  extern bool isMMX;
152 #endif
153 
154 
155 
156 
157 // Turn on ia32 ASM for Ciphers and Message Digests
158 // Seperate define since these are more complex, use member offsets
159 // and user may want to turn off while leaving Big Integer optos on
160 #if defined(TAOCRYPT_X86ASM_AVAILABLE) && !defined(DISABLE_TAO_ASM)
161  #define TAO_ASM
162 #endif
163 
164 
165 // Extra word in older vtable implementations, for ASM member offset
166 #if defined(__GNUC__) && __GNUC__ < 3
167  #define OLD_GCC_OFFSET
168 #endif
169 
170 
171 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
172 # define TAOCRYPT_MALLOC_ALIGNMENT_IS_16
173 #endif
174 
175 #if defined(__linux__) || defined(__sun__) || defined(__CYGWIN__)
176 # define TAOCRYPT_MEMALIGN_AVAILABLE
177 #endif
178 
179 
180 #if defined(_WIN32) || defined(__CYGWIN__)
181  #define TAOCRYPT_WIN32_AVAILABLE
182 #endif
183 
184 #if defined(__unix__) || defined(__MACH__)
185  #define TAOCRYPT_UNIX_AVAILABLE
186 #endif
187 
188 
189 // VC60 workaround: it doesn't allow typename in some places
190 #if defined(_MSC_VER) && (_MSC_VER < 1300)
191  #define CPP_TYPENAME
192 #else
193  #define CPP_TYPENAME typename
194 #endif
195 
196 
197 #ifdef _MSC_VER
198  #define TAOCRYPT_NO_VTABLE __declspec(novtable)
199 #else
200  #define TAOCRYPT_NO_VTABLE
201 #endif
202 
203 
204 #ifdef USE_SYS_STL
205  // use system STL
206  #define STL_NAMESPACE std
207 #else
208  // use mySTL
209  #define STL_NAMESPACE mySTL
210 #endif
211 
212 
213 // ***************** DLL related ********************
214 
215 #ifdef TAOCRYPT_WIN32_AVAILABLE
216 
217 #ifdef TAOCRYPT_EXPORTS
218  #define TAOCRYPT_IS_DLL
219  #define TAOCRYPT_DLL __declspec(dllexport)
220 #elif defined(TAOCRYPT_IMPORTS)
221  #define TAOCRYPT_IS_DLL
222  #define TAOCRYPT_DLL __declspec(dllimport)
223 #else
224  #define TAOCRYPT_DLL
225 #endif // EXPORTS
226 
227 #define TAOCRYPT_API __stdcall
228 #define TAOCRYPT_CDECL __cdecl
229 
230 #else // TAOCRYPT_WIN32_AVAILABLE
231 
232 #define TAOCRYPT_DLL
233 #define TAOCRYPT_API
234 #define TAOCRYPT_CDECL
235 
236 #endif // TAOCRYPT_WIN32_AVAILABLE
237 
238 
239 // ****************** tempalte stuff *******************
240 
241 
242 #if defined(TAOCRYPT_MANUALLY_INSTANTIATE_TEMPLATES) && \
243  !defined(TAOCRYPT_IMPORTS)
244  #define TAOCRYPT_DLL_TEMPLATE_CLASS template class TAOCRYPT_DLL
245 #elif defined(__MWERKS__)
246  #define TAOCRYPT_DLL_TEMPLATE_CLASS extern class TAOCRYPT_DLL
247 #else
248  #define TAOCRYPT_DLL_TEMPLATE_CLASS extern template class TAOCRYPT_DLL
249 #endif
250 
251 
252 #if defined(TAOCRYPT_MANUALLY_INSTANTIATE_TEMPLATES) && \
253  !defined(TAOCRYPT_EXPORTS)
254  #define TAOCRYPT_STATIC_TEMPLATE_CLASS template class
255 #elif defined(__MWERKS__)
256  #define TAOCRYPT_STATIC_TEMPLATE_CLASS extern class
257 #else
258  #define TAOCRYPT_STATIC_TEMPLATE_CLASS extern template class
259 #endif
260 
261 
262 // ************** compile-time assertion ***************
263 
264 template <bool b>
266 {
267  static char dummy[2*b-1];
268 };
269 
270 #define TAOCRYPT_COMPILE_ASSERT(assertion) \
271  TAOCRYPT_COMPILE_ASSERT_INSTANCE(assertion, __LINE__)
272 
273 #if defined(TAOCRYPT_EXPORTS) || defined(TAOCRYPT_IMPORTS)
274  #define TAOCRYPT_COMPILE_ASSERT_INSTANCE(assertion, instance)
275 #else
276  #define TAOCRYPT_COMPILE_ASSERT_INSTANCE(assertion, instance) \
277  (void)sizeof(CompileAssert<(assertion)>)
278 #endif
279 
280 #define TAOCRYPT_ASSERT_JOIN(X, Y) TAOCRYPT_DO_ASSERT_JOIN(X, Y)
281 
282 #define TAOCRYPT_DO_ASSERT_JOIN(X, Y) X##Y
283 
284 
285 /*************** helpers *****************************/
286 
287 inline unsigned int BitsToBytes(unsigned int bitCount)
288 {
289  return ((bitCount+7)/(8));
290 }
291 
292 inline unsigned int BytesToWords(unsigned int byteCount)
293 {
294  return ((byteCount+WORD_SIZE-1)/WORD_SIZE);
295 }
296 
297 inline unsigned int BitsToWords(unsigned int bitCount)
298 {
299  return ((bitCount+WORD_BITS-1)/(WORD_BITS));
300 }
301 
302 inline void CopyWords(word* r, const word* a, word32 n)
303 {
304  for (word32 i = 0; i < n; i++)
305  r[i] = a[i];
306 }
307 
308 inline unsigned int CountWords(const word* X, unsigned int N)
309 {
310  while (N && X[N-1]==0)
311  N--;
312  return N;
313 }
314 
315 inline void SetWords(word* r, word a, unsigned int n)
316 {
317  for (unsigned int i=0; i<n; i++)
318  r[i] = a;
319 }
320 
321 enum ByteOrder { LittleEndianOrder = 0, BigEndianOrder = 1 };
322 enum CipherDir {ENCRYPTION, DECRYPTION};
323 
324 inline CipherDir ReverseDir(CipherDir dir)
325 {
326  return (dir == ENCRYPTION) ? DECRYPTION : ENCRYPTION;
327 }
328 
329 template <typename ENUM_TYPE, int VALUE>
331 {
332  static ENUM_TYPE ToEnum() { return (ENUM_TYPE)VALUE; }
333 };
334 
337 
338 
339 #ifndef BIG_ENDIAN_ORDER
340  typedef LittleEndian HostByteOrder;
341 #else
342  typedef BigEndian HostByteOrder;
343 #endif
344 
345 inline ByteOrder GetHostByteOrder()
346 {
347  return HostByteOrder::ToEnum();
348 }
349 
350 inline bool HostByteOrderIs(ByteOrder order)
351 {
352  return order == GetHostByteOrder();
353 }
354 
355 
356 void xorbuf(byte*, const byte*, unsigned int);
357 
358 
359 template <class T>
360 inline bool IsPowerOf2(T n)
361 {
362  return n > 0 && (n & (n-1)) == 0;
363 }
364 
365 template <class T1, class T2>
366 inline T2 ModPowerOf2(T1 a, T2 b)
367 {
368  return T2(a) & (b-1);
369 }
370 
371 template <class T>
372 inline T RoundDownToMultipleOf(T n, T m)
373 {
374  return n - (IsPowerOf2(m) ? ModPowerOf2(n, m) : (n%m));
375 }
376 
377 template <class T>
378 inline T RoundUpToMultipleOf(T n, T m)
379 {
380  return RoundDownToMultipleOf(n+m-1, m);
381 }
382 
383 template <class T>
384 inline unsigned int GetAlignment(T* dummy = 0) // VC60 workaround
385 {
386 #if (_MSC_VER >= 1300)
387  return __alignof(T);
388 #elif defined(__GNUC__)
389  return __alignof__(T);
390 #else
391  return sizeof(T);
392 #endif
393 }
394 
395 inline bool IsAlignedOn(const void* p, unsigned int alignment)
396 {
397  return IsPowerOf2(alignment) ? ModPowerOf2((size_t)p, alignment) == 0
398  : (size_t)p % alignment == 0;
399 }
400 
401 template <class T>
402 inline bool IsAligned(const void* p, T* dummy = 0) // VC60 workaround
403 {
404  return IsAlignedOn(p, GetAlignment<T>());
405 }
406 
407 
408 template <class T> inline T rotlFixed(T x, unsigned int y)
409 {
410  return (x<<y) | (x>>(sizeof(T)*8-y));
411 }
412 
413 template <class T> inline T rotrFixed(T x, unsigned int y)
414 {
415  return (x>>y) | (x<<(sizeof(T)*8-y));
416 }
417 
418 #ifdef INTEL_INTRINSICS
419 
420 #pragma intrinsic(_lrotl, _lrotr)
421 
422 template<> inline word32 rotlFixed(word32 x, word32 y)
423 {
424  return y ? _lrotl(x, y) : x;
425 }
426 
427 template<> inline word32 rotrFixed(word32 x, word32 y)
428 {
429  return y ? _lrotr(x, y) : x;
430 }
431 
432 #endif // INTEL_INTRINSICS
433 
434 #ifdef min
435 #undef min
436 #endif
437 
438 
439 template <class T>
440 inline const T& min(const T& a, const T& b)
441 {
442  return a < b ? a : b;
443 }
444 
445 
446 inline word32 ByteReverse(word32 value)
447 {
448 #ifdef PPC_INTRINSICS
449  // PPC: load reverse indexed instruction
450  return (word32)__lwbrx(&value,0);
451 #elif defined(FAST_ROTATE)
452  // 5 instructions with rotate instruction, 9 without
453  return (rotrFixed(value, 8U) & 0xff00ff00) |
454  (rotlFixed(value, 8U) & 0x00ff00ff);
455 #else
456  // 6 instructions with rotate instruction, 8 without
457  value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8);
458  return rotlFixed(value, 16U);
459 #endif
460 }
461 
462 
463 #ifdef WORD64_AVAILABLE
464 
465 inline word64 ByteReverse(word64 value)
466 {
467 #ifdef TAOCRYPT_SLOW_WORD64
468  return (word64(ByteReverse(word32(value))) << 32) |
469  ByteReverse(word32(value>>32));
470 #else
471  value = ((value & W64LIT(0xFF00FF00FF00FF00)) >> 8) |
472  ((value & W64LIT(0x00FF00FF00FF00FF)) << 8);
473  value = ((value & W64LIT(0xFFFF0000FFFF0000)) >> 16) |
474  ((value & W64LIT(0x0000FFFF0000FFFF)) << 16);
475  return rotlFixed(value, 32U);
476 #endif
477 }
478 
479 #endif // WORD64_AVAILABLE
480 
481 
482 template <typename T>
483 inline void ByteReverse(T* out, const T* in, word32 byteCount)
484 {
485  word32 count = byteCount/sizeof(T);
486  for (word32 i=0; i<count; i++)
487  out[i] = ByteReverse(in[i]);
488 }
489 
490 inline void ByteReverse(byte* out, const byte* in, word32 byteCount)
491 {
492  word32* o = reinterpret_cast<word32*>(out);
493  const word32* i = reinterpret_cast<const word32*>(in);
494  ByteReverse(o, i, byteCount);
495 }
496 
497 
498 template <class T>
499 inline T ByteReverseIf(T value, ByteOrder order)
500 {
501  return HostByteOrderIs(order) ? value : ByteReverse(value);
502 }
503 
504 
505 template <typename T>
506 inline void ByteReverseIf(T* out, const T* in, word32 bc, ByteOrder order)
507 {
508  if (!HostByteOrderIs(order))
509  ByteReverse(out, in, bc);
510  else if (out != in)
511  memcpy(out, in, bc);
512 }
513 
514 
515 
516 // do Asm Reverse is host is Little and x86asm
517 #ifdef LITTLE_ENDIAN_ORDER
518  #ifdef TAOCRYPT_X86ASM_AVAILABLE
519  #define LittleReverse AsmReverse
520  #else
521  #define LittleReverse ByteReverse
522  #endif
523 #else
524  #define LittleReverse
525 #endif
526 
527 
528 // do Asm Reverse is host is Big and x86asm
529 #ifdef BIG_ENDIAN_ORDER
530  #ifdef TAOCRYPT_X86ASM_AVAILABLE
531  #define BigReverse AsmReverse
532  #else
533  #define BigReverse ByteReverse
534  #endif
535 #else
536  #define BigReverse
537 #endif
538 
539 
540 #ifdef TAOCRYPT_X86ASM_AVAILABLE
541 
542  // faster than rotate, use bswap
543 
544  inline word32 AsmReverse(word32 wd)
545  {
546  #ifdef __GNUC__
547  __asm__
548  (
549  "bswap %1"
550  : "=r"(wd)
551  : "0"(wd)
552  );
553  #else
554  __asm
555  {
556  mov eax, wd
557  bswap eax
558  mov wd, eax
559  }
560  #endif
561  return wd;
562  }
563 
564 #endif
565 
566 
567 template <class T>
568 inline void GetUserKey(ByteOrder order, T* out, word32 outlen, const byte* in,
569  word32 inlen)
570 {
571  const unsigned int U = sizeof(T);
572  memcpy(out, in, inlen);
573  memset((byte *)out+inlen, 0, outlen*U-inlen);
574  ByteReverseIf(out, out, RoundUpToMultipleOf(inlen, U), order);
575 }
576 
577 
578 #ifdef _MSC_VER
579  // disable conversion warning
580  // 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy
581  #pragma warning(disable:4244 4996)
582 #endif
583 
584 
585 inline byte UnalignedGetWordNonTemplate(ByteOrder order, const byte *block,
586  byte*)
587 {
588  return block[0];
589 }
590 
591 inline word16 UnalignedGetWordNonTemplate(ByteOrder order, const byte* block,
592  word16*)
593 {
594  return (order == BigEndianOrder)
595  ? block[1] | (block[0] << 8)
596  : block[0] | (block[1] << 8);
597 }
598 
599 inline word32 UnalignedGetWordNonTemplate(ByteOrder order, const byte* block,
600  word32*)
601 {
602  return (order == BigEndianOrder)
603  ? word32(block[3]) | (word32(block[2]) << 8) | (word32(block[1]) << 16)
604  | (word32(block[0]) << 24)
605  : word32(block[0]) | (word32(block[1]) << 8) | (word32(block[2]) << 16)
606  | (word32(block[3]) << 24);
607 }
608 
609 template <class T>
610 inline T UnalignedGetWord(ByteOrder order, const byte *block, T* dummy = 0)
611 {
612  return UnalignedGetWordNonTemplate(order, block, dummy);
613 }
614 
615 inline void UnalignedPutWord(ByteOrder order, byte *block, byte value,
616  const byte *xorBlock = 0)
617 {
618  block[0] = xorBlock ? (value ^ xorBlock[0]) : value;
619 }
620 
621 #define GETBYTE(x, y) (unsigned int)byte((x)>>(8*(y)))
622 
623 inline void UnalignedPutWord(ByteOrder order, byte *block, word16 value,
624  const byte *xorBlock = 0)
625 {
626  if (order == BigEndianOrder)
627  {
628  block[0] = GETBYTE(value, 1);
629  block[1] = GETBYTE(value, 0);
630  }
631  else
632  {
633  block[0] = GETBYTE(value, 0);
634  block[1] = GETBYTE(value, 1);
635  }
636 
637  if (xorBlock)
638  {
639  block[0] ^= xorBlock[0];
640  block[1] ^= xorBlock[1];
641  }
642 }
643 
644 inline void UnalignedPutWord(ByteOrder order, byte* block, word32 value,
645  const byte* xorBlock = 0)
646 {
647  if (order == BigEndianOrder)
648  {
649  block[0] = GETBYTE(value, 3);
650  block[1] = GETBYTE(value, 2);
651  block[2] = GETBYTE(value, 1);
652  block[3] = GETBYTE(value, 0);
653  }
654  else
655  {
656  block[0] = GETBYTE(value, 0);
657  block[1] = GETBYTE(value, 1);
658  block[2] = GETBYTE(value, 2);
659  block[3] = GETBYTE(value, 3);
660  }
661 
662  if (xorBlock)
663  {
664  block[0] ^= xorBlock[0];
665  block[1] ^= xorBlock[1];
666  block[2] ^= xorBlock[2];
667  block[3] ^= xorBlock[3];
668  }
669 }
670 
671 
672 template <class T>
673 inline T GetWord(bool assumeAligned, ByteOrder order, const byte *block)
674 {
675  if (assumeAligned)
676  return ByteReverseIf(*reinterpret_cast<const T *>(block), order);
677  else
678  return UnalignedGetWord<T>(order, block);
679 }
680 
681 template <class T>
682 inline void GetWord(bool assumeAligned, ByteOrder order, T &result,
683  const byte *block)
684 {
685  result = GetWord<T>(assumeAligned, order, block);
686 }
687 
688 template <class T>
689 inline void PutWord(bool assumeAligned, ByteOrder order, byte* block, T value,
690  const byte *xorBlock = 0)
691 {
692  if (assumeAligned)
693  {
694  if (xorBlock)
695  *reinterpret_cast<T *>(block) = ByteReverseIf(value, order)
696  ^ *reinterpret_cast<const T *>(xorBlock);
697  else
698  *reinterpret_cast<T *>(block) = ByteReverseIf(value, order);
699  }
700  else
701  UnalignedPutWord(order, block, value, xorBlock);
702 }
703 
704 template <class T, class B, bool A=true>
705 class GetBlock
706 {
707 public:
708  GetBlock(const void *block)
709  : m_block((const byte *)block) {}
710 
711  template <class U>
712  inline GetBlock<T, B, A> & operator()(U &x)
713  {
714  TAOCRYPT_COMPILE_ASSERT(sizeof(U) >= sizeof(T));
715  x = GetWord<T>(A, B::ToEnum(), m_block);
716  m_block += sizeof(T);
717  return *this;
718  }
719 
720 private:
721  const byte *m_block;
722 };
723 
724 template <class T, class B, bool A = true>
725 class PutBlock
726 {
727 public:
728  PutBlock(const void *xorBlock, void *block)
729  : m_xorBlock((const byte *)xorBlock), m_block((byte *)block) {}
730 
731  template <class U>
732  inline PutBlock<T, B, A> & operator()(U x)
733  {
734  PutWord(A, B::ToEnum(), m_block, (T)x, m_xorBlock);
735  m_block += sizeof(T);
736  if (m_xorBlock)
737  m_xorBlock += sizeof(T);
738  return *this;
739  }
740 
741 private:
742  const byte *m_xorBlock;
743  byte *m_block;
744 };
745 
746 /*
747  XXX MYSQL: Setting A (assumeAligned) to false,
748  keeping it true might trigger segfault on SPARC.
749 */
750 template <class T, class B, bool A= false>
752 {
753  // function needed because of C++ grammatical ambiguity between
754  // expression-statements and declarations
755  static inline GetBlock<T, B, A> Get(const void *block)
756  {return GetBlock<T, B, A>(block);}
757  typedef PutBlock<T, B, A> Put;
758 };
759 
760 
761 
762 template <bool overflow> struct SafeShifter;
763 
764 template<> struct SafeShifter<true>
765 {
766  template <class T>
767  static inline T RightShift(T value, unsigned int bits)
768  {
769  return 0;
770  }
771 
772  template <class T>
773  static inline T LeftShift(T value, unsigned int bits)
774  {
775  return 0;
776  }
777 };
778 
779 template<> struct SafeShifter<false>
780 {
781  template <class T>
782  static inline T RightShift(T value, unsigned int bits)
783  {
784  return value >> bits;
785  }
786 
787  template <class T>
788  static inline T LeftShift(T value, unsigned int bits)
789  {
790  return value << bits;
791  }
792 };
793 
794 template <unsigned int bits, class T>
795 inline T SafeRightShift(T value)
796 {
797  return SafeShifter<(bits>=(8*sizeof(T)))>::RightShift(value, bits);
798 }
799 
800 template <unsigned int bits, class T>
801 inline T SafeLeftShift(T value)
802 {
803  return SafeShifter<(bits>=(8*sizeof(T)))>::LeftShift(value, bits);
804 }
805 
806 
807 inline
808 word ShiftWordsLeftByBits(word* r, unsigned int n, unsigned int shiftBits)
809 {
810  word u, carry=0;
811  if (shiftBits)
812  for (unsigned int i=0; i<n; i++)
813  {
814  u = r[i];
815  r[i] = (u << shiftBits) | carry;
816  carry = u >> (WORD_BITS-shiftBits);
817  }
818  return carry;
819 }
820 
821 
822 inline
823 word ShiftWordsRightByBits(word* r, unsigned int n, unsigned int shiftBits)
824 {
825  word u, carry=0;
826  if (shiftBits)
827  for (int i=n-1; i>=0; i--)
828  {
829  u = r[i];
830  r[i] = (u >> shiftBits) | carry;
831  carry = u << (WORD_BITS-shiftBits);
832  }
833  return carry;
834 }
835 
836 
837 inline
838 void ShiftWordsLeftByWords(word* r, unsigned int n, unsigned int shiftWords)
839 {
840  shiftWords = min(shiftWords, n);
841  if (shiftWords)
842  {
843  for (unsigned int i=n-1; i>=shiftWords; i--)
844  r[i] = r[i-shiftWords];
845  SetWords(r, 0, shiftWords);
846  }
847 }
848 
849 
850 inline
851 void ShiftWordsRightByWords(word* r, unsigned int n, unsigned int shiftWords)
852 {
853  shiftWords = min(shiftWords, n);
854  if (shiftWords)
855  {
856  for (unsigned int i=0; i+shiftWords<n; i++)
857  r[i] = r[i+shiftWords];
858  SetWords(r+n-shiftWords, 0, shiftWords);
859  }
860 }
861 
862 
863 template <class T1, class T2>
864 inline T1 SaturatingSubtract(T1 a, T2 b)
865 {
866  TAOCRYPT_COMPILE_ASSERT_INSTANCE(T1(-1)>0, 0); // T1 is unsigned type
867  TAOCRYPT_COMPILE_ASSERT_INSTANCE(T2(-1)>0, 1); // T2 is unsigned type
868  return T1((a > b) ? (a - b) : 0);
869 }
870 
871 
872 // declares
873 unsigned int BytePrecision(word value);
874 unsigned int BitPrecision(word);
875 word Crop(word value, unsigned int size);
876 
877 
878 
879 } // namespace
880 
881 #endif // TAO_CRYPT_MISC_HPP