random_without_cast_overflow.h
Go to the documentation of this file.
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>
19  static SrcScalar value() { return internal::random<SrcScalar>(); }
20 };
21 
22 // Signed to unsigned integer widening cast.
23 template <typename SrcScalar, typename TgtScalar>
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>
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>
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>
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>
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>
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>
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>
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>
123  SrcScalar, TgtScalar,
124  typename internal::enable_if<NumTraits<SrcScalar>::IsComplex && !NumTraits<TgtScalar>::IsComplex>::type> {
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>
132  SrcScalar, TgtScalar,
133  typename internal::enable_if<!NumTraits<SrcScalar>::IsComplex && NumTraits<TgtScalar>::IsComplex>::type> {
136 };
137 
138 // Complex to complex.
139 template <typename SrcScalar, typename TgtScalar>
141  SrcScalar, TgtScalar,
142  typename internal::enable_if<NumTraits<SrcScalar>::IsComplex && NumTraits<TgtScalar>::IsComplex>::type> {
145  static SrcScalar value() {
148  }
149 };
150 
151 } // namespace internal
152 } // namespace Eigen
Scalar * b
Definition: benchVecAdd.cpp:17
Namespace containing all symbols from the Eigen library.
Definition: jet.h:637
Definition: pytypes.h:1370


gtsam
Author(s):
autogenerated on Tue Jul 4 2023 02:35:29