-
Notifications
You must be signed in to change notification settings - Fork 62
/
scale.h
72 lines (61 loc) · 2.48 KB
/
scale.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// Copyright John McFarlane 2018.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file ../LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#if !defined(CNL_IMPL_NUM_TRAITS_SCALE)
#define CNL_IMPL_NUM_TRAITS_SCALE
#include "../power_value.h"
#include "../type_traits/enable_if.h"
#include "../type_traits/is_integral.h"
namespace cnl {
template<int Digits, int Radix, class S, class Enable = void>
struct scale;
namespace _impl {
// fundamental integer-friendly cnl::scale algorithm
template<int Digits, int Radix, typename S, class Enable = void>
struct default_scale;
template<int Digits, int Radix, typename S>
struct default_scale<Digits, Radix, S, _impl::enable_if_t<0<=Digits>> {
CNL_NODISCARD constexpr auto operator()(S const& s) const
-> decltype(s*power_value<S, Digits, Radix>())
{
return s*power_value<S, Digits, Radix>();
}
};
// cnl::default_scale<-ve, cnl::constant<>>
template<int Digits, int Radix, typename S>
struct default_scale<Digits, Radix, S, _impl::enable_if_t<Digits<0>> {
CNL_NODISCARD constexpr auto operator()(S const& s) const
-> decltype(s/power_value<S, -Digits, Radix>())
{
return s/power_value<S, -Digits, Radix>();
}
};
}
// cnl::scale<..., fundamental-integer>
template<int Digits, int Radix, class S>
struct scale<Digits, Radix, S, _impl::enable_if_t<cnl::_impl::is_integral<S>::value>>
: _impl::default_scale<Digits, Radix, S> {
};
template<int Digits, int Radix, template<typename, typename>
class TNUM, typename S, typename Tag>
struct scale<Digits, Radix, TNUM<S, Tag>, _impl::enable_if_t<(
Digits<0 && cnl::_impl::is_integral<S>::value)>>
{
CNL_NODISCARD constexpr auto operator()(TNUM<S, Tag> const& s) const
-> decltype(s/_impl::power_value<S, -Digits, Radix>())
{
return s/_impl::power_value<S, -Digits, Radix>();
}
};
namespace _impl {
// cnl::_impl::scale - convenience wrapper for cnl::scale
template<int Digits, int Radix=2, class S>
CNL_NODISCARD constexpr auto scale(S const& s)
-> decltype(cnl::scale<Digits, Radix, S>{}(s))
{
return cnl::scale<Digits, Radix, S>{}(s);
}
}
}
#endif // CNL_IMPL_NUM_TRAITS_SCALE