Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F102562463
random_without_cast_overflow.h
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sat, Feb 22, 00:53
Size
7 KB
Mime Type
text/x-c++
Expires
Mon, Feb 24, 00:53 (2 d)
Engine
blob
Format
Raw Data
Handle
24359990
Attached To
rDLMA Diffusion limited mixed aggregation
random_without_cast_overflow.h
View Options
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2020 C. Antonio Sanchez <cantonios@google.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// Utilities for generating random numbers without overflows, which might
// otherwise result in undefined behavior.
namespace
Eigen
{
namespace
internal
{
// Default implementation assuming SrcScalar fits into TgtScalar.
template
<
typename
SrcScalar
,
typename
TgtScalar
,
typename
EnableIf
=
void
>
struct
random_without_cast_overflow
{
static
SrcScalar
value
()
{
return
internal
::
random
<
SrcScalar
>
();
}
};
// Signed to unsigned integer widening cast.
template
<
typename
SrcScalar
,
typename
TgtScalar
>
struct
random_without_cast_overflow
<
SrcScalar
,
TgtScalar
,
typename
internal
::
enable_if
<
NumTraits
<
SrcScalar
>::
IsInteger
&&
NumTraits
<
TgtScalar
>::
IsInteger
&&
!
NumTraits
<
TgtScalar
>::
IsSigned
&&
(
std
::
numeric_limits
<
SrcScalar
>::
digits
<
std
::
numeric_limits
<
TgtScalar
>::
digits
||
(
std
::
numeric_limits
<
SrcScalar
>::
digits
==
std
::
numeric_limits
<
TgtScalar
>::
digits
&&
NumTraits
<
SrcScalar
>::
IsSigned
))
>::
type
>
{
static
SrcScalar
value
()
{
SrcScalar
a
=
internal
::
random
<
SrcScalar
>
();
return
a
<
SrcScalar
(
0
)
?
-
(
a
+
1
)
:
a
;
}
};
// Integer to unsigned narrowing cast.
template
<
typename
SrcScalar
,
typename
TgtScalar
>
struct
random_without_cast_overflow
<
SrcScalar
,
TgtScalar
,
typename
internal
::
enable_if
<
NumTraits
<
SrcScalar
>::
IsInteger
&&
NumTraits
<
TgtScalar
>::
IsInteger
&&
!
NumTraits
<
SrcScalar
>::
IsSigned
&&
(
std
::
numeric_limits
<
SrcScalar
>::
digits
>
std
::
numeric_limits
<
TgtScalar
>::
digits
)
>::
type
>
{
static
SrcScalar
value
()
{
TgtScalar
b
=
internal
::
random
<
TgtScalar
>
();
return
static_cast
<
SrcScalar
>
(
b
<
TgtScalar
(
0
)
?
-
(
b
+
1
)
:
b
);
}
};
// Integer to signed narrowing cast.
template
<
typename
SrcScalar
,
typename
TgtScalar
>
struct
random_without_cast_overflow
<
SrcScalar
,
TgtScalar
,
typename
internal
::
enable_if
<
NumTraits
<
SrcScalar
>::
IsInteger
&&
NumTraits
<
TgtScalar
>::
IsInteger
&&
NumTraits
<
SrcScalar
>::
IsSigned
&&
(
std
::
numeric_limits
<
SrcScalar
>::
digits
>
std
::
numeric_limits
<
TgtScalar
>::
digits
)
>::
type
>
{
static
SrcScalar
value
()
{
return
static_cast
<
SrcScalar
>
(
internal
::
random
<
TgtScalar
>
());
}
};
// Unsigned to signed integer narrowing cast.
template
<
typename
SrcScalar
,
typename
TgtScalar
>
struct
random_without_cast_overflow
<
SrcScalar
,
TgtScalar
,
typename
internal
::
enable_if
<
NumTraits
<
SrcScalar
>::
IsInteger
&&
NumTraits
<
TgtScalar
>::
IsInteger
&&
!
NumTraits
<
SrcScalar
>::
IsSigned
&&
NumTraits
<
TgtScalar
>::
IsSigned
&&
(
std
::
numeric_limits
<
SrcScalar
>::
digits
==
std
::
numeric_limits
<
TgtScalar
>::
digits
)
>::
type
>
{
static
SrcScalar
value
()
{
return
internal
::
random
<
SrcScalar
>
()
/
2
;
}
};
// Floating-point to integer, full precision.
template
<
typename
SrcScalar
,
typename
TgtScalar
>
struct
random_without_cast_overflow
<
SrcScalar
,
TgtScalar
,
typename
internal
::
enable_if
<
!
NumTraits
<
SrcScalar
>::
IsInteger
&&
!
NumTraits
<
SrcScalar
>::
IsComplex
&&
NumTraits
<
TgtScalar
>::
IsInteger
&&
(
std
::
numeric_limits
<
TgtScalar
>::
digits
<=
std
::
numeric_limits
<
SrcScalar
>::
digits
)
>::
type
>
{
static
SrcScalar
value
()
{
return
static_cast
<
SrcScalar
>
(
internal
::
random
<
TgtScalar
>
());
}
};
// Floating-point to integer, narrowing precision.
template
<
typename
SrcScalar
,
typename
TgtScalar
>
struct
random_without_cast_overflow
<
SrcScalar
,
TgtScalar
,
typename
internal
::
enable_if
<
!
NumTraits
<
SrcScalar
>::
IsInteger
&&
!
NumTraits
<
SrcScalar
>::
IsComplex
&&
NumTraits
<
TgtScalar
>::
IsInteger
&&
(
std
::
numeric_limits
<
TgtScalar
>::
digits
>
std
::
numeric_limits
<
SrcScalar
>::
digits
)
>::
type
>
{
static
SrcScalar
value
()
{
// NOTE: internal::random<T>() is limited by RAND_MAX, so random<int64_t> is always within that range.
// This prevents us from simply shifting bits, which would result in only 0 or -1.
// Instead, keep least-significant K bits and sign.
static
const
TgtScalar
KeepMask
=
(
static_cast
<
TgtScalar
>
(
1
)
<<
std
::
numeric_limits
<
SrcScalar
>::
digits
)
-
1
;
const
TgtScalar
a
=
internal
::
random
<
TgtScalar
>
();
return
static_cast
<
SrcScalar
>
(
a
>
TgtScalar
(
0
)
?
(
a
&
KeepMask
)
:
-
(
a
&
KeepMask
));
}
};
// Integer to floating-point, re-use above logic.
template
<
typename
SrcScalar
,
typename
TgtScalar
>
struct
random_without_cast_overflow
<
SrcScalar
,
TgtScalar
,
typename
internal
::
enable_if
<
NumTraits
<
SrcScalar
>::
IsInteger
&&
!
NumTraits
<
TgtScalar
>::
IsInteger
&&
!
NumTraits
<
TgtScalar
>::
IsComplex
>::
type
>
{
static
SrcScalar
value
()
{
return
static_cast
<
SrcScalar
>
(
random_without_cast_overflow
<
TgtScalar
,
SrcScalar
>::
value
());
}
};
// Floating-point narrowing conversion.
template
<
typename
SrcScalar
,
typename
TgtScalar
>
struct
random_without_cast_overflow
<
SrcScalar
,
TgtScalar
,
typename
internal
::
enable_if
<!
NumTraits
<
SrcScalar
>::
IsInteger
&&
!
NumTraits
<
SrcScalar
>::
IsComplex
&&
!
NumTraits
<
TgtScalar
>::
IsInteger
&&
!
NumTraits
<
TgtScalar
>::
IsComplex
&&
(
std
::
numeric_limits
<
SrcScalar
>::
digits
>
std
::
numeric_limits
<
TgtScalar
>::
digits
)
>::
type
>
{
static
SrcScalar
value
()
{
return
static_cast
<
SrcScalar
>
(
internal
::
random
<
TgtScalar
>
());
}
};
// Complex to non-complex.
template
<
typename
SrcScalar
,
typename
TgtScalar
>
struct
random_without_cast_overflow
<
SrcScalar
,
TgtScalar
,
typename
internal
::
enable_if
<
NumTraits
<
SrcScalar
>::
IsComplex
&&
!
NumTraits
<
TgtScalar
>::
IsComplex
>::
type
>
{
typedef
typename
NumTraits
<
SrcScalar
>::
Real
SrcReal
;
static
SrcScalar
value
()
{
return
SrcScalar
(
random_without_cast_overflow
<
SrcReal
,
TgtScalar
>::
value
(),
0
);
}
};
// Non-complex to complex.
template
<
typename
SrcScalar
,
typename
TgtScalar
>
struct
random_without_cast_overflow
<
SrcScalar
,
TgtScalar
,
typename
internal
::
enable_if
<!
NumTraits
<
SrcScalar
>::
IsComplex
&&
NumTraits
<
TgtScalar
>::
IsComplex
>::
type
>
{
typedef
typename
NumTraits
<
TgtScalar
>::
Real
TgtReal
;
static
SrcScalar
value
()
{
return
random_without_cast_overflow
<
SrcScalar
,
TgtReal
>::
value
();
}
};
// Complex to complex.
template
<
typename
SrcScalar
,
typename
TgtScalar
>
struct
random_without_cast_overflow
<
SrcScalar
,
TgtScalar
,
typename
internal
::
enable_if
<
NumTraits
<
SrcScalar
>::
IsComplex
&&
NumTraits
<
TgtScalar
>::
IsComplex
>::
type
>
{
typedef
typename
NumTraits
<
SrcScalar
>::
Real
SrcReal
;
typedef
typename
NumTraits
<
TgtScalar
>::
Real
TgtReal
;
static
SrcScalar
value
()
{
return
SrcScalar
(
random_without_cast_overflow
<
SrcReal
,
TgtReal
>::
value
(),
random_without_cast_overflow
<
SrcReal
,
TgtReal
>::
value
());
}
};
}
// namespace internal
}
// namespace Eigen
Event Timeline
Log In to Comment