Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F17577408
math.hpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Size
6 KB
Referenced Files
None
Subscribers
None
math.hpp
View Options
//===-- rosa/support/math.hpp -----------------------------------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file rosa/support/math.hpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
/// \date 2017
///
/// \brief Math helpers.
///
//===----------------------------------------------------------------------===//
// !!!!!! Please check lines 60 - 180 forward !!!!!!!!!!!!!!
#ifndef ROSA_SUPPORT_MATH_HPP
#define ROSA_SUPPORT_MATH_HPP
#include
"debug.hpp"
#include
<algorithm>
#include
<array>
#include
<cmath>
#include
<cstdarg>
#include
<cstdlib>
#include
<limits>
#include
<type_traits>
namespace
rosa
{
/// Computes log base 2 of a number.
///
/// \param N the number to compute log base 2 for
///
/// \return log base 2 of \p N
constexpr
size_t
log2
(
const
size_t
N
)
{
return
((
N
<
2
)
?
1
:
1
+
log2
(
N
/
2
));
}
/// Tells the next representable floating point value.
///
/// \tparam T type to operate on
///
/// \note The second type argument enforces \p T being a floating point type,
/// always use the default value!
///
/// \param V value to which find the next representable one
///
/// \return the next representable value of type \p T after value \p V
///
/// \pre Type \p T must be a floating point type, which is enforced by
/// `std::enable_if` in the second type argument.
template
<
typename
T
,
typename
=
std
::
enable_if_t
<
std
::
is_floating_point
<
T
>::
value
>>
T
nextRepresentableFloatingPoint
(
const
T
V
)
{
return
std
::
nextafter
(
V
,
std
::
numeric_limits
<
T
>::
infinity
());
}
#if false
// copied from the internet and adapted
//
(
https
:
//stackoverflow.com/questions/1657883/variable-number-of-arguments-in-c)
/// Conjuncts two or more values with each other.
///
/// \param two or more values of the same datatype
///
/// \return the conjunction of the values given as parameter.
template
<
typename
CONFDATATYPE
>
CONFDATATYPE
fuzzyAND
(
int
n_args
,
...)
noexcept
{
// TODO: check datatype, if there are at least two arguments, and if they are
// between 0 and 1
// David suggests: nstead of a variadic argument, you could pass the values as
// an std::array (with a template argument for the length). When you pass the
// values as a container, you can simply use std::max_element and
// std::min_element to have a one-liner implementation of the these fuzzy
// functions.
va_list
ap
;
va_start
(
ap
,
n_args
);
CONFDATATYPE
min
=
va_arg
(
ap
,
CONFDATATYPE
);
for
(
int
i
=
2
;
i
<=
n_args
;
i
++
)
{
CONFDATATYPE
a
=
va_arg
(
ap
,
CONFDATATYPE
);
min
=
std
::
min
(
a
,
min
);
}
va_end
(
ap
);
return
min
;
}
#else
template
<
typename
CONFDATATYPE
,
std
::
size_t
size
>
CONFDATATYPE
fuzzyAND
(
std
::
array
<
CONFDATATYPE
,
size
>
Data
)
noexcept
{
STATIC_ASSERT
(
std
::
is_arithmetic
<
CONFDATATYPE
>::
value
,
"Type of FuzzyAnd is not arithmetic"
);
STATIC_ASSERT
(
size
>
1
,
"Number of Arguments is to little"
);
for
(
auto
tmp
:
Data
)
ASSERT
(
tmp
<=
1
&&
tmp
>=
0
);
return
*
std
::
min_element
(
Data
.
begin
(),
Data
.
end
());
}
#if false
// safer
template
<
typename
CONFDATATYPE
,
typename
...
_CONFDATATYPE
>
std
::
enable_if_t
<
std
::
conjunction_v
<
std
::
is_same
<
CONFDATATYPE
,
_CONFDATATYPE
>
...
>
,
CONFDATATYPE
>
fuzzyAND
(
CONFDATATYPE
Data
,
_CONFDATATYPE
...
Datan
)
noexcept
{
return
fuzzyAND
(
std
::
array
<
CONFDATATYPE
,
sizeof
...(
Datan
)
+
1
>
{
Data
,
Datan
...});
}
#else
template
<
typename
CONFDATATYPE
,
typename
...
_CONFDATATYPE
>
CONFDATATYPE
fuzzyAND
(
CONFDATATYPE
Data
,
_CONFDATATYPE
...
Datan
)
noexcept
{
return
fuzzyAND
(
std
::
array
<
CONFDATATYPE
,
sizeof
...(
Datan
)
+
1
>
{
Data
,
Datan
...});
}
#endif
#endif
#if false
//can't compile
/// Disjuncts two or more values with each other.
///
///
///
/// \return the disjunction of the values given as parameter.
// copied from the internet
// (https://stackoverflow.com/questions/1657883/variable-number-of-arguments-in-c)
template
<
typename
CONFDATATYPE
>
CONFDATATYPE
fuzzyOR
(
int
n_args
,
...)
noexcept
{
// TODO: check datatype and if they are between 0 and 1
// David suggests: nstead of a variadic argument, you could pass the values as
// an std::array (with a template argument for the length). When you pass the
// values as a container, you can simply use std::max_element and
// std::min_element to have a one-liner implementation of the these fuzzy
// functions.
va_list
ap
;
va_start
(
ap
,
n_args
);
CONFDATATYPE
max
=
va_arg
(
ap
,
CONFDATATYPE
);
for
(
int
i
=
2
;
i
<=
n_args
;
i
++
)
{
CONFDATATYPE
a
=
va_arg
(
ap
,
CONFDATATYPE
);
max
=
std
::
max
(
a
,
max
);
}
va_end
(
ap
);
return
max
;
}
#else
template
<
typename
CONFDATATYPE
,
std
::
size_t
size
>
CONFDATATYPE
fuzzyOR
(
std
::
array
<
CONFDATATYPE
,
size
>
Data
)
noexcept
{
STATIC_ASSERT
(
std
::
is_arithmetic
<
CONFDATATYPE
>::
value
,
"Type of FuzzyAnd is not arithmetic"
);
STATIC_ASSERT
(
size
>
1
,
"Number of Arguments is to little"
);
for
(
auto
tmp
:
Data
)
ASSERT
(
tmp
<=
1
&&
tmp
>=
0
);
return
*
std
::
max_element
(
Data
.
begin
(),
Data
.
end
());
}
#if false
// safer
template
<
typename
CONFDATATYPE
,
typename
...
_CONFDATATYPE
>
std
::
enable_if_t
<
std
::
conjunction_v
<
std
::
is_same
<
CONFDATATYPE
,
_CONFDATATYPE
>
...
>
,
CONFDATATYPE
>
fuzzyOR
(
CONFDATATYPE
Data
,
_CONFDATATYPE
...
Datan
)
noexcept
{
return
fuzzyOR
(
std
::
array
<
CONFDATATYPE
,
sizeof
...(
Datan
)
+
1
>
{
Data
,
Datan
...});
}
#else
template
<
typename
CONFDATATYPE
,
typename
...
_CONFDATATYPE
>
CONFDATATYPE
fuzzyOR
(
CONFDATATYPE
Data
,
_CONFDATATYPE
...
Datan
)
noexcept
{
return
fuzzyOR
(
std
::
array
<
CONFDATATYPE
,
sizeof
...(
Datan
)
+
1
>
{
Data
,
Datan
...});
}
#endif
#endif
template
<
typename
INDATATYPE
,
typename
PROCDATATYPE
>
PROCDATATYPE
relativeDistance
(
INDATATYPE
NewValue
,
INDATATYPE
HistoryValue
)
noexcept
{
PROCDATATYPE
Dist
=
HistoryValue
-
NewValue
;
if
(
Dist
==
0
)
{
return
0
;
}
else
{
Dist
=
Dist
/
NewValue
;
if
(
Dist
<
0
)
{
// TODO: I guess this multiplication here should not be done because
// it could be that the distance fuzzy functions are not symetrical
//(negative and positive side)
Dist
=
Dist
*
(
-1
);
}
return
(
Dist
);
}
}
}
// End namespace rosa
#endif
// ROSA_SUPPORT_MATH_HPP
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Sun, Jun 21, 1:08 AM (16 h, 22 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
330298
Default Alt Text
math.hpp (6 KB)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline
Log In to Comment