numerical-collection-cpp 0.10.0
A collection of algorithms in numerical analysis implemented in C++
Loading...
Searching...
No Matches
ternary_vector.h
Go to the documentation of this file.
1/*
2 * Copyright 2021 MusicScience37 (Kenta Kabashima)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
20#pragma once
21
22#include <algorithm>
23#include <cstddef>
24#include <cstdint>
25#include <functional>
26#include <limits>
27#include <utility>
28
29#include <Eigen/Core>
30
33
34namespace num_collect::opt::impl {
35
40public:
42 using digit_type = std::int8_t;
43
45 static constexpr index_type max_digits =
46 static_cast<index_type>(std::numeric_limits<digit_type>::max());
47
51 ternary_vector() = default;
52
60
66 [[nodiscard]] auto dim() const -> index_type { return data_.rows(); }
67
76 data_ = data_type::Zero(dim, init_digits_per_dimensions + 1);
77 }
78
85 [[nodiscard]] auto digits(index_type dim) const -> index_type {
87 return static_cast<index_type>(data_(dim, 0));
88 }
89
97 [[nodiscard]] auto operator()(index_type dim, index_type digit)
98 -> digit_type& {
101 return data_(dim, digit + 1);
102 }
103
111 [[nodiscard]] auto operator()(index_type dim, index_type digit) const
112 -> digit_type {
115 return data_(dim, digit + 1);
116 }
117
125 const auto next_digits = digits(dim) + 1;
126 if (next_digits >= data_.cols()) {
127 NUM_COLLECT_ASSERT(next_digits <= max_digits);
128 auto new_data = data_type(data_.rows(), next_digits + 1);
129 new_data.leftCols(data_.cols()) = data_;
130 data_ = std::move(new_data);
131 }
132 data_(dim, next_digits) = digit;
133 data_(dim, 0) = static_cast<digit_type>(next_digits);
134 }
135
142 [[nodiscard]] auto operator==(const ternary_vector& right) const -> bool {
143 NUM_COLLECT_ASSERT(data_.rows() == right.data_.rows());
144 for (index_type i = 0; i < data_.rows(); ++i) {
145 // NOLINTNEXTLINE: false positive
146 const auto left_digits = static_cast<index_type>(data_(i, 0));
147 const auto right_digits = // NOLINTNEXTLINE: false positive
148 static_cast<index_type>(right.data_(i, 0));
149 const auto min_digits = std::min(left_digits, right_digits);
150 for (index_type j = 0; j < min_digits; ++j) {
151 if (data_(i, j + 1) != right.data_(i, j + 1)) {
152 return false;
153 }
154 }
155 for (index_type j = min_digits; j < left_digits; ++j) {
156 if (data_(i, j + 1) != static_cast<digit_type>(0)) {
157 return false;
158 }
159 }
160 for (index_type j = min_digits; j < right_digits; ++j) {
161 if (right.data_(i, j + 1) != static_cast<digit_type>(0)) {
162 return false;
163 }
164 }
165 }
166 return true;
167 }
168
175 [[nodiscard]] auto operator!=(const ternary_vector& right) const -> bool {
176 return !operator==(right);
177 }
178
186 template <typename Scalar>
187 [[nodiscard]] auto elem_as(index_type dim) const -> Scalar {
189 const auto ndigits = digits(dim);
190 auto num = static_cast<Scalar>(0);
191 auto coeff = static_cast<Scalar>(1);
192 static const Scalar inv_base =
193 static_cast<Scalar>(1) / static_cast<Scalar>(3);
194 for (index_type i = 0; i < ndigits; ++i) {
195 num += coeff * static_cast<Scalar>(data_(dim, i + 1));
196 coeff *= inv_base;
197 }
198 return num;
199 }
200
201private:
203 using data_type = Eigen::Matrix<digit_type, Eigen::Dynamic, Eigen::Dynamic,
204 Eigen::RowMajor>;
205
208
216};
217
218} // namespace num_collect::opt::impl
219
220namespace std {
221
226template <>
227class hash<num_collect::opt::impl::ternary_vector> {
228public:
231
233 using result_type = std::size_t;
234
241 [[nodiscard]] auto operator()(const argument_type& vec) const
242 -> result_type {
243 std::size_t res = 0;
244 for (num_collect::index_type i = 0; i < vec.dim(); ++i) {
245 std::size_t temp = 0;
246 num_collect::index_type non_zero_digits = 0;
247 for (num_collect::index_type j = 0; j < vec.digits(i); ++j) {
248 if (vec(i, j) != 0) {
249 non_zero_digits = j + 1;
250 }
251 }
252 for (num_collect::index_type j = 0; j < non_zero_digits; ++j) {
253 constexpr std::size_t coeff = 3;
254 temp *= coeff;
255 temp += static_cast<std::size_t>(
256 static_cast<std::uint8_t>(vec(i, j)));
257 }
258 constexpr std::size_t coeff = 79865413; // a prime number
259 res *= coeff;
260 res += temp;
261 }
262 return res;
263 }
264};
265
266} // namespace std
Definition of assertion macros.
#define NUM_COLLECT_ASSERT(CONDITION)
Macro to check whether a condition is satisfied.
Definition assert.h:66
#define NUM_COLLECT_DEBUG_ASSERT(CONDITION)
Macro to check whether a condition is satisfied in debug build only.
Definition assert.h:75
Class of vectors of ternary floating-point numbers.
void change_dim(index_type dim)
Change the number of dimensions.
auto digits(index_type dim) const -> index_type
Get the number of digits of a dimension.
auto elem_as(index_type dim) const -> Scalar
Get the element of this vector as a floating-point number.
static constexpr index_type init_digits_per_dimensions
Initial digits per dimensions.
auto operator()(index_type dim, index_type digit) -> digit_type &
Access a digit.
std::int8_t digit_type
Type of a digit.
void push_back(index_type dim, digit_type digit)
Add a digit to a dimension.
auto operator!=(const ternary_vector &right) const -> bool
Compare with another object.
ternary_vector()=default
Constructor.
Eigen::Matrix< digit_type, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > data_type
Type of data matrix.
static constexpr index_type max_digits
Maximum number of digits per dimension.
auto operator==(const ternary_vector &right) const -> bool
Compare with another object.
auto dim() const -> index_type
Get the number of dimensions.
auto operator()(index_type dim, index_type digit) const -> digit_type
Access a digit.
ternary_vector(index_type dim)
Constructor.
auto operator()(const argument_type &vec) const -> result_type
Calculate hash.
Definition of index_type type.
std::ptrdiff_t index_type
Type of indices in this library.
Definition index_type.h:33
Namespace of internal implementations.
Namespace of num_collect source codes.
STL namespace.