Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. // random -*- C++ -*-
  2.  
  3. // Copyright (C) 2012-2013 Free Software Foundation, Inc.
  4. //
  5. // This file is part of the GNU ISO C++ Library.  This library is free
  6. // software; you can redistribute it and/or modify it under the
  7. // terms of the GNU General Public License as published by the
  8. // Free Software Foundation; either version 3, or (at your option)
  9. // any later version.
  10.  
  11. // This library is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. // GNU General Public License for more details.
  15.  
  16. // Under Section 7 of GPL version 3, you are granted additional
  17. // permissions described in the GCC Runtime Library Exception, version
  18. // 3.1, as published by the Free Software Foundation.
  19.  
  20. // You should have received a copy of the GNU General Public License and
  21. // a copy of the GCC Runtime Library Exception along with this program;
  22. // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
  23. // <http://www.gnu.org/licenses/>.
  24.  
  25. #include <random>
  26.  
  27. #ifdef  _GLIBCXX_USE_C99_STDINT_TR1
  28.  
  29. #if defined __i386__ || defined __x86_64__
  30. # include <cpuid.h>
  31. #endif
  32.  
  33.  
  34. namespace std _GLIBCXX_VISIBILITY(default)
  35. {
  36.  
  37.   namespace
  38.   {
  39.     static unsigned long
  40.     _M_strtoul(const std::string& __str)
  41.     {
  42.       unsigned long __ret = 5489UL;
  43.       if (__str != "mt19937")
  44.         {
  45.           const char* __nptr = __str.c_str();
  46.           char* __endptr;
  47.           __ret = std::strtoul(__nptr, &__endptr, 0);
  48.           if (*__nptr == '\0' || *__endptr != '\0')
  49.             std::__throw_runtime_error(__N("random_device::_M_strtoul"
  50.                                            "(const std::string&)"));
  51.         }
  52.       return __ret;
  53.     }
  54.  
  55. #if (defined __i386__ || defined __x86_64__) && defined _GLIBCXX_X86_RDRAND
  56.     unsigned int
  57.     __attribute__ ((target("rdrnd")))
  58.     __x86_rdrand(void)
  59.     {
  60.       unsigned int retries = 100;
  61.       unsigned int val;
  62.  
  63.       while (__builtin_ia32_rdrand32_step(&val) == 0)
  64.         if (--retries == 0)
  65.           std::__throw_runtime_error(__N("random_device::__x86_rdrand(void)"));
  66.  
  67.       return val;
  68.     }
  69. #endif
  70.   }
  71.  
  72.  
  73.   void
  74.   random_device::_M_init(const std::string& token)
  75.   {
  76.     const char *fname = token.c_str();
  77.  
  78.     if (token == "default")
  79.       {
  80. #if (defined __i386__ || defined __x86_64__) && defined _GLIBCXX_X86_RDRAND
  81.         unsigned int eax, ebx, ecx, edx;
  82.         // Check availability of cpuid and, for now at least, also the
  83.         // CPU signature for Intel's
  84.         if (__get_cpuid_max(0, &ebx) > 0 && ebx == signature_INTEL_ebx)
  85.           {
  86.             __cpuid(1, eax, ebx, ecx, edx);
  87.             if (ecx & bit_RDRND)
  88.               {
  89.                 _M_file = nullptr;
  90.                 return;
  91.               }
  92.           }
  93. #endif
  94.  
  95.         fname = "/dev/urandom";
  96.       }
  97.     else if (token != "/dev/urandom" && token != "/dev/random")
  98.     fail:
  99.       std::__throw_runtime_error(__N("random_device::"
  100.                                      "random_device(const std::string&)"));
  101.  
  102.     _M_file = std::fopen(fname, "rb");
  103.     if (! _M_file)
  104.       goto fail;
  105.   }
  106.  
  107.   void
  108.   random_device::_M_init_pretr1(const std::string& token)
  109.   {
  110.     _M_mt.seed(_M_strtoul(token));
  111.   }
  112.  
  113.   void
  114.   random_device::_M_fini()
  115.   {
  116.     if (_M_file)
  117.       std::fclose(_M_file);
  118.   }
  119.  
  120.   random_device::result_type
  121.   random_device::_M_getval()
  122.   {
  123. #if (defined __i386__ || defined __x86_64__) && defined _GLIBCXX_X86_RDRAND
  124.     if (! _M_file)
  125.       return __x86_rdrand();
  126. #endif
  127.  
  128.     result_type __ret;
  129.     std::fread(reinterpret_cast<void*>(&__ret), sizeof(result_type),
  130.                1, _M_file);
  131.     return __ret;
  132.   }
  133.  
  134.   random_device::result_type
  135.   random_device::_M_getval_pretr1()
  136.   {
  137.     return _M_mt();
  138.   }
  139.  
  140.   template class mersenne_twister_engine<
  141.     uint_fast32_t,
  142.     32, 624, 397, 31,
  143.     0x9908b0dfUL, 11,
  144.     0xffffffffUL, 7,
  145.     0x9d2c5680UL, 15,
  146.     0xefc60000UL, 18, 1812433253UL>;
  147. }
  148. #endif
  149.