cart-elc

Source code for CART-ELC
git clone git://git.laack.co/cart-elc.git
Log | Files | Refs | README | LICENSE

random_without_cast_overflow.h (7174B)


      1 // This file is part of Eigen, a lightweight C++ template library
      2 // for linear algebra.
      3 //
      4 // Copyright (C) 2020 C. Antonio Sanchez <cantonios@google.com>
      5 //
      6 // This Source Code Form is subject to the terms of the Mozilla
      7 // Public License v. 2.0. If a copy of the MPL was not distributed
      8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
      9 
     10 // Utilities for generating random numbers without overflows, which might
     11 // otherwise result in undefined behavior.
     12 
     13 namespace Eigen {
     14 namespace internal {
     15 
     16 // Default implementation assuming SrcScalar fits into TgtScalar.
     17 template <typename SrcScalar, typename TgtScalar, typename EnableIf = void>
     18 struct random_without_cast_overflow {
     19   static SrcScalar value() { return internal::random<SrcScalar>(); }
     20 };
     21 
     22 // Signed to unsigned integer widening cast.
     23 template <typename SrcScalar, typename TgtScalar>
     24 struct random_without_cast_overflow<
     25     SrcScalar, TgtScalar,
     26     typename internal::enable_if<NumTraits<SrcScalar>::IsInteger && NumTraits<TgtScalar>::IsInteger &&
     27                                  !NumTraits<TgtScalar>::IsSigned &&
     28                                  (std::numeric_limits<SrcScalar>::digits < std::numeric_limits<TgtScalar>::digits ||
     29                                   (std::numeric_limits<SrcScalar>::digits == std::numeric_limits<TgtScalar>::digits &&
     30                                    NumTraits<SrcScalar>::IsSigned))>::type> {
     31   static SrcScalar value() {
     32     SrcScalar a = internal::random<SrcScalar>();
     33     return a < SrcScalar(0) ? -(a + 1) : a;
     34   }
     35 };
     36 
     37 // Integer to unsigned narrowing cast.
     38 template <typename SrcScalar, typename TgtScalar>
     39 struct random_without_cast_overflow<
     40     SrcScalar, TgtScalar,
     41     typename internal::enable_if<
     42         NumTraits<SrcScalar>::IsInteger && NumTraits<TgtScalar>::IsInteger && !NumTraits<SrcScalar>::IsSigned &&
     43         (std::numeric_limits<SrcScalar>::digits > std::numeric_limits<TgtScalar>::digits)>::type> {
     44   static SrcScalar value() {
     45     TgtScalar b = internal::random<TgtScalar>();
     46     return static_cast<SrcScalar>(b < TgtScalar(0) ? -(b + 1) : b);
     47   }
     48 };
     49 
     50 // Integer to signed narrowing cast.
     51 template <typename SrcScalar, typename TgtScalar>
     52 struct random_without_cast_overflow<
     53     SrcScalar, TgtScalar,
     54     typename internal::enable_if<
     55         NumTraits<SrcScalar>::IsInteger && NumTraits<TgtScalar>::IsInteger && NumTraits<SrcScalar>::IsSigned &&
     56         (std::numeric_limits<SrcScalar>::digits > std::numeric_limits<TgtScalar>::digits)>::type> {
     57   static SrcScalar value() { return static_cast<SrcScalar>(internal::random<TgtScalar>()); }
     58 };
     59 
     60 // Unsigned to signed integer narrowing cast.
     61 template <typename SrcScalar, typename TgtScalar>
     62 struct random_without_cast_overflow<
     63     SrcScalar, TgtScalar,
     64     typename internal::enable_if<NumTraits<SrcScalar>::IsInteger && NumTraits<TgtScalar>::IsInteger &&
     65                                  !NumTraits<SrcScalar>::IsSigned && NumTraits<TgtScalar>::IsSigned &&
     66                                  (std::numeric_limits<SrcScalar>::digits ==
     67                                   std::numeric_limits<TgtScalar>::digits)>::type> {
     68   static SrcScalar value() { return internal::random<SrcScalar>() / 2; }
     69 };
     70 
     71 // Floating-point to integer, full precision.
     72 template <typename SrcScalar, typename TgtScalar>
     73 struct random_without_cast_overflow<
     74     SrcScalar, TgtScalar,
     75     typename internal::enable_if<
     76         !NumTraits<SrcScalar>::IsInteger && !NumTraits<SrcScalar>::IsComplex && NumTraits<TgtScalar>::IsInteger &&
     77         (std::numeric_limits<TgtScalar>::digits <= std::numeric_limits<SrcScalar>::digits)>::type> {
     78   static SrcScalar value() { return static_cast<SrcScalar>(internal::random<TgtScalar>()); }
     79 };
     80 
     81 // Floating-point to integer, narrowing precision.
     82 template <typename SrcScalar, typename TgtScalar>
     83 struct random_without_cast_overflow<
     84     SrcScalar, TgtScalar,
     85     typename internal::enable_if<
     86         !NumTraits<SrcScalar>::IsInteger && !NumTraits<SrcScalar>::IsComplex && NumTraits<TgtScalar>::IsInteger &&
     87         (std::numeric_limits<TgtScalar>::digits > std::numeric_limits<SrcScalar>::digits)>::type> {
     88   static SrcScalar value() {
     89     // NOTE: internal::random<T>() is limited by RAND_MAX, so random<int64_t> is always within that range.
     90     // This prevents us from simply shifting bits, which would result in only 0 or -1.
     91     // Instead, keep least-significant K bits and sign.
     92     static const TgtScalar KeepMask = (static_cast<TgtScalar>(1) << std::numeric_limits<SrcScalar>::digits) - 1;
     93     const TgtScalar a = internal::random<TgtScalar>();
     94     return static_cast<SrcScalar>(a > TgtScalar(0) ? (a & KeepMask) : -(a & KeepMask));
     95   }
     96 };
     97 
     98 // Integer to floating-point, re-use above logic.
     99 template <typename SrcScalar, typename TgtScalar>
    100 struct random_without_cast_overflow<
    101     SrcScalar, TgtScalar,
    102     typename internal::enable_if<NumTraits<SrcScalar>::IsInteger && !NumTraits<TgtScalar>::IsInteger &&
    103                                  !NumTraits<TgtScalar>::IsComplex>::type> {
    104   static SrcScalar value() {
    105     return static_cast<SrcScalar>(random_without_cast_overflow<TgtScalar, SrcScalar>::value());
    106   }
    107 };
    108 
    109 // Floating-point narrowing conversion.
    110 template <typename SrcScalar, typename TgtScalar>
    111 struct random_without_cast_overflow<
    112     SrcScalar, TgtScalar,
    113     typename internal::enable_if<!NumTraits<SrcScalar>::IsInteger && !NumTraits<SrcScalar>::IsComplex &&
    114                                  !NumTraits<TgtScalar>::IsInteger && !NumTraits<TgtScalar>::IsComplex &&
    115                                  (std::numeric_limits<SrcScalar>::digits >
    116                                   std::numeric_limits<TgtScalar>::digits)>::type> {
    117   static SrcScalar value() { return static_cast<SrcScalar>(internal::random<TgtScalar>()); }
    118 };
    119 
    120 // Complex to non-complex.
    121 template <typename SrcScalar, typename TgtScalar>
    122 struct random_without_cast_overflow<
    123     SrcScalar, TgtScalar,
    124     typename internal::enable_if<NumTraits<SrcScalar>::IsComplex && !NumTraits<TgtScalar>::IsComplex>::type> {
    125   typedef typename NumTraits<SrcScalar>::Real SrcReal;
    126   static SrcScalar value() { return SrcScalar(random_without_cast_overflow<SrcReal, TgtScalar>::value(), 0); }
    127 };
    128 
    129 // Non-complex to complex.
    130 template <typename SrcScalar, typename TgtScalar>
    131 struct random_without_cast_overflow<
    132     SrcScalar, TgtScalar,
    133     typename internal::enable_if<!NumTraits<SrcScalar>::IsComplex && NumTraits<TgtScalar>::IsComplex>::type> {
    134   typedef typename NumTraits<TgtScalar>::Real TgtReal;
    135   static SrcScalar value() { return random_without_cast_overflow<SrcScalar, TgtReal>::value(); }
    136 };
    137 
    138 // Complex to complex.
    139 template <typename SrcScalar, typename TgtScalar>
    140 struct random_without_cast_overflow<
    141     SrcScalar, TgtScalar,
    142     typename internal::enable_if<NumTraits<SrcScalar>::IsComplex && NumTraits<TgtScalar>::IsComplex>::type> {
    143   typedef typename NumTraits<SrcScalar>::Real SrcReal;
    144   typedef typename NumTraits<TgtScalar>::Real TgtReal;
    145   static SrcScalar value() {
    146     return SrcScalar(random_without_cast_overflow<SrcReal, TgtReal>::value(),
    147                      random_without_cast_overflow<SrcReal, TgtReal>::value());
    148   }
    149 };
    150 
    151 }  // namespace internal
    152 }  // namespace Eigen