Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
runtime_precision.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "precision.hpp"
4#include "scalar_traits.hpp"
5#include <optional>
6
7namespace uni20
8{
10template <typename T> inline constexpr bool has_runtime_precision_v = false;
11#if UNI20_HAS_MPREAL
12template <> inline constexpr bool has_runtime_precision_v<mpreal> = true;
13#endif
14#if UNI20_HAS_MPREAL
15template <> inline constexpr bool has_runtime_precision_v<mpcomplex> = true;
16#endif
17
18namespace detail
19{
20template <class T> struct precision_component
21{
22 using type = T;
23};
24template <class T>
25 requires is_complex_v<T>
26struct precision_component<T>
27{
28 using type = make_real_t<T>;
29};
30template <class T> using precision_component_t = typename precision_component<std::remove_cvref_t<T>>::type;
31} // namespace detail
32
36template <class T>
37 requires(!has_runtime_precision_v<std::remove_cvref_t<T>>) && requires {
38 numeric_limits<detail::precision_component_t<T>>::digits();
39 numeric_limits<detail::precision_component_t<T>>::is_exact;
40 }
41[[nodiscard]] constexpr Precision native_precision()
42{
43 using R = detail::precision_component_t<T>;
44 if constexpr (numeric_limits<R>::is_exact)
45 return Precision::exact();
46 else
48}
49
51template <class T>
52 requires requires(T const& value) { value.precision(); } || requires { native_precision<T>(); }
53[[nodiscard]] constexpr Precision precision_of(T const& value)
54{
55 if constexpr (requires { value.precision(); })
56 return value.precision();
57 else
58 return native_precision<T>();
59}
60
64template <class T>
65 requires(has_runtime_precision_v<std::remove_cvref_t<T>> || requires { native_precision<T>(); })
67{
68 if constexpr (!has_runtime_precision_v<std::remove_cvref_t<T>>)
69 if (p != native_precision<T>()) throw std::invalid_argument("fixed-precision scalar requires its native precision");
70}
71
73template <class S, class V>
74 requires((requires { native_precision<S>(); } && std::constructible_from<S, V const&>) ||
75 (has_runtime_precision_v<S> && std::constructible_from<S, V const&, Precision>))
76[[nodiscard]] constexpr S scalar_at_precision(V const& value, Precision p)
77{
78 require_precision<S>(p);
79 if constexpr (has_runtime_precision_v<S>)
80 return S(value, p);
81 else
82 return S(value);
83}
84
85namespace detail
86{
87// Empty for fixed-precision values; owners and views need no extra runtime state.
88template <typename T, bool = has_runtime_precision_v<std::remove_cv_t<T>>> struct precision_default
89{};
90#if UNI20_HAS_MPREAL
91template <typename T> struct precision_default<T, true>
92{
93 std::optional<Precision> value = {};
94
95 Precision get() const
96 {
97 if (!value) throw std::logic_error("tensor: no default working precision was supplied");
98 return *value;
99 }
100 Precision default_precision() const { return this->get(); }
101 void default_precision(Precision p) { value = p; }
102 std::optional<Precision> default_precision_if_set() const noexcept { return value; }
103};
104#endif
105} // namespace detail
106} // namespace uni20
Exact arithmetic or an explicit binary working precision.
Definition core/precision.hpp:13
static constexpr Precision bits(bit_count_type count)
Select a positive binary significand size.
Definition core/precision.hpp:21
static constexpr Precision exact() noexcept
No approximation has been selected; rational arithmetic remains exact.
Definition core/precision.hpp:17
locale_t value
Definition data_table.cpp:49
typename make_real< T >::type make_real_t
Alias for the underlying real-valued type of T.
Definition scalar_traits.hpp:168
Definition data_table.cpp:8
Definition async/async.hpp:26
constexpr Precision precision_of(T const &value)
Read scalar precision without changing any scalar or provider state.
Definition runtime_precision.hpp:53
constexpr bool has_runtime_precision_v
Whether numerical values of this scalar family carry runtime precision.
Definition runtime_precision.hpp:10
constexpr S scalar_at_precision(V const &value, Precision p)
Construct or convert a scalar at one explicit precision.
Definition runtime_precision.hpp:76
constexpr bool is_exact(detail::standard_complex< T > const &x)
A standard complex value is exact only when both components are exact.
Definition math.hpp:50
constexpr void require_precision(Precision p)
Reject an operation precision incompatible with a fixed scalar result.
Definition runtime_precision.hpp:66
constexpr Precision native_precision()
Concrete precision of a fixed scalar family, including complex components.
Definition runtime_precision.hpp:41
Project-level numeric limits customization point.
Definition numeric_limits.hpp:16