Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. // random -*- C++ -*-
  2.  
  3. // Copyright (C) 2012-2015 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. #define _GLIBCXX_USE_CXX11_ABI 1
  26. #include <random>
  27.  
  28. #ifdef  _GLIBCXX_USE_C99_STDINT_TR1
  29.  
  30. #if defined __i386__ || defined __x86_64__
  31. # include <cpuid.h>
  32. #endif
  33.  
  34. #include <cerrno>
  35. #include <cstdio>
  36.  
  37. #ifdef _GLIBCXX_HAVE_UNISTD_H
  38. # include <unistd.h>
  39. #endif
  40.  
  41. namespace std _GLIBCXX_VISIBILITY(default)
  42. {
  43.   namespace
  44.   {
  45.     static unsigned long
  46.     _M_strtoul(const std::string& __str)
  47.     {
  48.       unsigned long __ret = 5489UL;
  49.       if (__str != "mt19937")
  50.         {
  51.           const char* __nptr = __str.c_str();
  52.           char* __endptr;
  53.           __ret = std::strtoul(__nptr, &__endptr, 0);
  54.           if (*__nptr == '\0' || *__endptr != '\0')
  55.             std::__throw_runtime_error(__N("random_device::_M_strtoul"
  56.                                            "(const std::string&)"));
  57.         }
  58.       return __ret;
  59.     }
  60.  
  61. #if (defined __i386__ || defined __x86_64__) && defined _GLIBCXX_X86_RDRAND
  62.     unsigned int
  63.     __attribute__ ((target("rdrnd")))
  64.     __x86_rdrand(void)
  65.     {
  66.       unsigned int retries = 100;
  67.       unsigned int val;
  68.  
  69.       while (__builtin_ia32_rdrand32_step(&val) == 0)
  70.         if (--retries == 0)
  71.           std::__throw_runtime_error(__N("random_device::__x86_rdrand(void)"));
  72.  
  73.       return val;
  74.     }
  75. #endif
  76.   }
  77.  
  78.   void
  79.   random_device::_M_init(const std::string& token)
  80.   {
  81.     const char *fname = token.c_str();
  82.  
  83.     if (token == "default")
  84.       {
  85. #if (defined __i386__ || defined __x86_64__) && defined _GLIBCXX_X86_RDRAND
  86.         unsigned int eax, ebx, ecx, edx;
  87.         // Check availability of cpuid and, for now at least, also the
  88.         // CPU signature for Intel's
  89.         if (__get_cpuid_max(0, &ebx) > 0 && ebx == signature_INTEL_ebx)
  90.           {
  91.             __cpuid(1, eax, ebx, ecx, edx);
  92.             if (ecx & bit_RDRND)
  93.               {
  94.                 _M_file = nullptr;
  95.                 return;
  96.               }
  97.           }
  98. #endif
  99.  
  100.         fname = "/dev/urandom";
  101.       }
  102.     else if (token != "/dev/urandom" && token != "/dev/random")
  103.     fail:
  104.       std::__throw_runtime_error(__N("random_device::"
  105.                                      "random_device(const std::string&)"));
  106.  
  107.     _M_file = static_cast<void*>(std::fopen(fname, "rb"));
  108.     if (!_M_file)
  109.       goto fail;
  110.   }
  111.  
  112.   void
  113.   random_device::_M_init_pretr1(const std::string& token)
  114.   {
  115.     _M_mt.seed(_M_strtoul(token));
  116.   }
  117.  
  118.   void
  119.   random_device::_M_fini()
  120.   {
  121.     if (_M_file)
  122.       std::fclose(static_cast<FILE*>(_M_file));
  123.   }
  124.  
  125.   random_device::result_type
  126.   random_device::_M_getval()
  127.   {
  128. #if (defined __i386__ || defined __x86_64__) && defined _GLIBCXX_X86_RDRAND
  129.     if (!_M_file)
  130.       return __x86_rdrand();
  131. #endif
  132.  
  133.     result_type __ret;
  134.     void* p = &__ret;
  135.     size_t n = sizeof(result_type);
  136. #ifdef _GLIBCXX_HAVE_UNISTD_H
  137.     do
  138.       {
  139.         const int e = read(fileno(static_cast<FILE*>(_M_file)), p, n);
  140.         if (e > 0)
  141.           {
  142.             n -= e;
  143.             p = static_cast<char*>(p) + e;
  144.           }
  145.         else if (e != -1 || errno != EINTR)
  146.           __throw_runtime_error(__N("random_device could not be read"));
  147.       }
  148.     while (n > 0);
  149. #else
  150.     const size_t e = std::fread(p, n, 1, static_cast<FILE*>(_M_file));
  151.     if (e != 1)
  152.       __throw_runtime_error(__N("random_device could not be read"));
  153. #endif
  154.  
  155.     return __ret;
  156.   }
  157.  
  158.   random_device::result_type
  159.   random_device::_M_getval_pretr1()
  160.   {
  161.     return _M_mt();
  162.   }
  163.  
  164.   template class mersenne_twister_engine<
  165.     uint_fast32_t,
  166.     32, 624, 397, 31,
  167.     0x9908b0dfUL, 11,
  168.     0xffffffffUL, 7,
  169.     0x9d2c5680UL, 15,
  170.     0xefc60000UL, 18, 1812433253UL>;
  171. }
  172. #endif
  173.