StatMech
Loading...
Searching...
No Matches
BaseNnumber.hpp
Go to the documentation of this file.
1#pragma once
2
4#include <iostream>
5#include <cerrno>
6#include <cassert>
7
8#ifndef __NVCC__
9 #define __host__
10 #define __device__
11#endif
12
18template<typename Integer = int>
20 private:
21 Integer m_base = 0;
22 Integer m_length = 0;
23 Integer m_max = 0;
24 mutable Integer m_register;
25
26 public:
27 __host__ __device__ BaseConverter() {}
34 __host__ __device__ BaseConverter(Integer Base, Integer Length)
35 : m_base(Base), m_length(Length), m_max(powi(Base, Length)) {}
36
37 __host__ __device__ BaseConverter(BaseConverter<Integer> const& other)
38 : m_base(other.base()), m_length(other.length()), m_max(other.maxVal()) {}
39
47 __host__ void status(void) const {
48 std::cout << "baseConverter.status()"
49 << "\n"
50 << "\tBase: " << this->m_base << "\n"
51 << "\tLength: " << this->m_length << "\n"
52 << "\tMax: " << this->m_max - 1 << "\n"
53 << "\tRegistered value: " << this->m_register << std::endl;
54 }
55 __host__ __device__ Integer base() const { return this->m_base; }
56 __host__ __device__ Integer length() const { return this->m_length; }
57 __host__ __device__ Integer maxVal() const { return this->m_max; }
58 __host__ __device__ Integer value() const { return this->m_register; }
59
69 //
70 template<typename Input,
71 typename std::enable_if_t< !std::is_integral_v<Input> >* = nullptr >
72 __host__ __device__ BaseConverter const& set(Input config) const {
73 static_assert(std::is_integral<Input>::value == false);
74 Integer num = 0, base = 1;
75 for(Integer pos = 0; pos < m_length; ++pos) {
76 num += config.at(m_length - 1 - pos) * base;
77 base *= m_base;
78 }
79 this->m_register = num;
80 return *this;
81 }
82 template<typename Input>
83 __host__ __device__ BaseConverter const& set(Input num) const {
84 static_assert(std::is_integral<Input>::value == true);
85 this->m_register = num;
86 return *this;
87 }
88
94 __host__ __device__ BaseConverter& setParam(Integer Base, Integer Length) {
95 this->m_base = Base;
96 this->m_length = Length;
97 this->m_max = powi(Base, Length);
98 return *this;
99 }
100
113 __host__ __device__ Integer digit(Integer const num, Integer const pos, Integer const base,
114 Integer const length) const {
115 Integer Pos
116 = (pos % length + length) % length; // taking care of negative values of 'trans'
117 return (num / powi(base, Pos % length)) % base;
118 }
119 __host__ __device__ Integer digit(Integer const num, Integer const pos) const {
120 return this->digit(num, pos, m_base, m_length);
121 }
122 __host__ __device__ Integer digit(Integer const pos) const {
123 return this->digit(m_register, pos, m_base, m_length);
124 }
125
139 __host__ __device__ Integer shiftDigits(Integer const num, Integer const trans,
140 Integer const base, Integer const length) const {
141 Integer Trans
142 = (trans % length + length) % length; // taking care of negative values of 'trans'
143 Integer temp = powi(base, Trans);
144 return (num / temp) + (num % temp) * powi(base, length - Trans);
145 }
146
147 __host__ __device__ Integer shiftDigits(Integer const num, Integer const trans) const {
148 return this->shiftDigits(num, trans, m_base, m_length);
149 }
150
151 __host__ __device__ BaseConverter const& shiftDigits(Integer const trans) const {
152 this->m_register = this->shiftDigits(m_register, trans, m_base, m_length);
153 return *this;
154 }
155
165 template<typename Input>
166 __host__ __device__ Integer digitsToNumber(Input const& digits, Integer const base,
167 Integer const length) const {
168 Integer res = 0, p = 1;
169 for(int l = length - 1; l >= 0; --l) {
170 res += p * digits[l];
171 p *= base;
172 }
173 return res;
174 }
175 template<typename Input>
176 __host__ __device__ Integer digitsToNumber(Input const& digits) const {
177 return this->digitsToNumber(digits, m_base, m_length);
178 }
179
190 template<typename Output>
191 __host__ __device__ auto printInDigits(Output& output, Integer const num,
192 Integer const base, Integer const length) const ->
193 typename std::enable_if< std::is_integral<Output>::value == false,
194 BaseConverter const&>::type {
195 static_assert(std::is_integral<Output>::value == false);
196 if(num >= powi(base, length)) {
197#ifndef __CUDA_ARCH__
198 std::cerr << "Warning:" << __PRETTY_FUNCTION__ << "\n\t"
199 << "Input(" << num
200 << ") cannot be expressed with base " << base << " and length " << length
201 << "." << std::endl;
202#endif
203 }
204 if(output.size() < length) output.resize(length);
205 for(int l = 0; l < length; ++l) {
206 output[l] = this->digit(num, length - l - 1, base, length);
207 }
208 return *this;
209 }
210 template<typename Output>
211 __host__ __device__ auto printInDigits(Output& output, Integer const num) const ->
212 typename std::enable_if< std::is_integral<Output>::value == false,
213 BaseConverter const&>::type {
214 static_assert(std::is_integral<Output>::value == false);
215 this->printInDigits(output, num, m_base, m_length);
216 return *this;
217 }
218 template<typename Output,
219 typename std::enable_if_t< !std::is_integral_v<Output> >* = nullptr >
220 __host__ __device__ BaseConverter const& printInDigits(Output& output) const {
221 static_assert(std::is_integral<Output>::value == false);
222 this->printInDigits(output, m_register, m_base, m_length);
223 return *this;
224 }
225
226 __host__ BaseConverter const& printInDigits(Integer const num, Integer const base,
227 Integer const length) const {
228 if(num >= powi(base, length)) {
229 std::cerr << "Warning(" << __func__ << "): Input(" << num
230 << ") cannot be expressed with base " << base << " and length " << length
231 << "." << std::endl;
232 }
233 for(int l = length - 1; l >= 0; --l) {
234 std::cout << this->digit(num, l, base, length) << " ";
235 }
236 std::cout << std::endl;
237 return *this;
238 }
239 // template<typename Input>
240 __host__ BaseConverter const& printInDigits(Integer const num) const {
241 // static_assert(std::is_integral<Input>::value == true);
242 this->printInDigits(num, m_base, m_length);
243 return *this;
244 }
245 __host__ BaseConverter const& printInDigits() const {
246 this->printInDigits(m_register, m_base, m_length);
247 return *this;
248 }
249};
250
251// template<typename Integer, typename Vector>
252// class generalBaseConverter {
253// Integer m_max;
254// Integer m_register;
255
256// static inline __device__ __host__ Integer powi(Integer base, Integer exponent) {
257// static_assert(std::is_integral<Integer>::value,
258// "Base and exponent number must be integers.");
259// if(exponent < 0) {
260// std::cout << "Error(" << __func__ << "): Exponent must be non-negative."
261// << std::endl;
262// std::exit(EXIT_FAILURE);
263// }
264// Integer res = 1;
265// for(int i = 0; i < exponent; ++i) res *= base;
266// return res;
267// }
268
269// static inline __device__ __host__ Integer MaxVal(Vector Base, Integer Length) {
270// Integer res = 1;
271// for(int i = 0; i < Length; ++i) res *= Base.at(i);
272// return res-1;
273// }
274
275// public:
276// /**
277// * @brief Construct a new BaseConverter object
278// *
279// * @param[in] Base
280// * @param[in] Length
281// */
282// generalBaseConverter(Vector Base, Integer Length)
283// : m_base(Base), m_length(Length), m_max(1) {
284// if(Base.size() < Length) {
285// std::cerr << "Base.size(" << Base.size() << ") < Length(" << Length << ")" << std::endl;
286// std::exit(EINVAL);
287// }
288// m_max = this->MaxVal(Base, Length);
289// }
290
291// /**
292// * @brief Show the status of the instance
293// * @li Base: Base of the positional notation to which the input number will converted
294// * @li Length: Number of digits in the resulting expression
295// * @li Max: The maximum integer representable with given Base and Length
296// * @li Registered value: An integer currently held by the instance
297// */
298// void status(void) const {
299// std::cout << "baseConverter.status()"
300// << "\n"
301// << "\tBase: ";
302// for(int pos = 0; pos < m_length; ++pos) { std::cout << m_base[pos] << " "; }
303// std::cout << "\n"
304// << "\tLength: " << this->m_length << "\n"
305// << "\tMax: " << this->m_max - 1 << "\n"
306// << "\tRegistered value: " << this->m_register << std::endl;
307// }
308// Integer base(int pos) const { return this->m_base.at(pos); }
309// Integer length() const { return this->m_length; }
310// Integer Max() const { return this->m_max; }
311// Integer value() const { return this->m_register; }
312
313// /**
314// * @brief
315// *
316// * @param num An integer to be held by the instance
317// * @param digits An array of integers
318// * which is to be held by the instance after converted to an integer
319// * in terms of the positional notation with base=this->base() and length=this->length()
320// * @return BaseConverter& Reference to the instance itself
321// */
322// template<typename Input>
323// generalBaseConverter& set(Input digits) {
324// Integer num = 0, base = 1;
325// for(int pos = 0; pos < m_Length; ++pos) {
326// num += digits[pos] * base;
327// base *= m_base[pos];
328// }
329// this->m_register = num;
330// return *this;
331// }
332// generalBaseConverter& set(Integer num) {
333// this->m_register = num;
334// return *this;
335// }
336
337// /**
338// * @brief Set the base and the length of the positional notation to which the input number will converted
339// * @param Base: Base of the positional notation to which the number will converted
340// * @param Length: Number of digits in the resulting expression
341// */
342// generalBaseConverter& setParam(Vector Base, Integer Length) {
343// this->m_base.resize(Length);
344// std::copy(Base.begin(), Base.end() + Length, this->m_base.begin());
345// this->m_length = Length;
346// this->m_max = this->MaxVal(Base, Length);
347// return *this;
348// }
349
350// /**
351// * @brief Returns the (pos)-th digit of the input (num) in given base and length.
352// *
353// * @param[in] num [default = this->value()] An integer the (pos)-th digit of which is to be returned.
354// * @param[in] pos The position of digit starting from zero.
355// * Negative value specifies the position in the reverse order.
356// * For example, setting pos=-1 returns the (length-1)-th digit.
357// * @param[in] base [default = this->base()] Base of the positional notation.
358// * @param[in] length [default = this->length()] Length of the positional notation
359// * with respect to with a negative value of (pos) is interpreted.
360// * @return Integer The (pos)-th digit of (num) in the positional notation with given (base) and (length).
361// */
362// __device__ __host__ Integer Digit(Integer const num, Integer const pos, Vector const Base,
363// Integer const length) const {
364// // taking care of negative values of 'pos'
365// Integer Pos = (pos % length + length) % length;
366// Integer base = 1;
367// for(int l = 0; l < Pos; ++l) base *= Base[l];
368// return (num / base) % Base[Pos];
369// }
370// __device__ __host__ Integer Digit(Integer const num, Integer const pos) const {
371// return Digit(num, pos, m_base, m_length);
372// }
373// __device__ __host__ Integer Digit(Integer const pos) const {
374// return Digit(m_register, pos, m_base, m_length);
375// }
376
377// /**
378// * @brief Converts an array of integers to the corresponding integer in terms of the positional notation with given (base) and (length)
379// *
380// * @tparam Output Container of Integers
381// * @param[in] digits An array of Integers representing a number in the positional notation with given (base) and (length)
382// * @param[in] base [default = this->base()] Base of the positional notation.
383// * @param[in] length [default = this->length()] Length of the positional notation.
384// * @return Integer
385// */
386// template<typename Input>
387// __device__ __host__ Integer DigitsToNumber(Input const& digits, Vector const Base,
388// Integer const length) const {
389// Integer res = 0, p = 1;
390// for(int l = length - 1; l >= 0; --l) {
391// if(digits[l] >= Base[l]) std::exit(EINVAL);
392// res += p * digits[l];
393// p *= Base[l];
394// }
395// return res;
396// }
397// template<typename Input>
398// __device__ __host__ Integer DigitsToNumber(Input const& digits) const {
399// return DigitsToNumber(digits, m_base, m_length);
400// }
401
402// /**
403// * @brief Expresses an integer (num) in the positional notation with given (base) and (length)
404// *
405// * @tparam Output Container of Integers
406// * @param[out] output [default = std::cout] An array to which the resulting expression is stored.
407// * @param[in] num [default = this->value()] An integer to be expressed in the positional notation with given (base) and (length)
408// * @param[in] base [default = this->base()] Base of the positional notation.
409// * @param[in] length [default = this->length()] Length of the positional notation.
410// * @return BaseConverter& Reference to the instance itself
411// */
412// template<typename Output>
413// __device__ __host__ generalBaseConverter& printInDigits(Output& output, Integer const num,
414// Vector const Base, Integer const Length) {
415// if(num > MaxVal(Base, length)) {
416// std::cerr << "Warning(" << __func__ << "): Input(" << num
417// << ") cannot be expressed with base " << Base << " and length " << Length
418// << "." << std::endl;
419// }
420// for(int l = 0; l < Length; ++l) {
421// output[l] = Digit(num, Length - l - 1, Base, Length);
422// }
423// return *this;
424// }
425// template<typename Output>
426// __device__ __host__ generalBaseConverter& printInDigits(Output& output, Integer const num) {
427// printInDigits(output, num, m_base, m_length);
428// return *this;
429// }
430// template<typename Output>
431// __device__ __host__ generalBaseConverter& printInDigits(Output& output) {
432// printInDigits(output, m_register, m_base, m_length);
433// return *this;
434// }
435
436// __device__ __host__ generalBaseConverter& printInDigits(Integer const num, Vector const Base,
437// Integer const Length) {
438// if(num > MaxVal(Base, Length)) {
439// std::cerr << "Warning(" << __func__ << "): Input(" << num
440// << ") cannot be expressed with base " << Base << " and length " << Length
441// << "." << std::endl;
442// }
443// for(int l = Length - 1; l >= 0; --l) {
444// std::cout << Digit(num, l, Base, Length) << " ";
445// }
446// std::cout << std::endl;
447// return *this;
448// }
449// __device__ __host__ generalBaseConverter& printInDigits(Integer const num) {
450// printInDigits(num, m_base, m_length);
451// return *this;
452// }
453// __device__ __host__ generalBaseConverter& printInDigits() {
454// printInDigits(m_register, m_base, m_length);
455// return *this;
456// }
457// };
Provides utilities for converting an integer to the corresponding expression in the positional notati...
Definition BaseNnumber.hpp:19
__host__ __device__ Integer value() const
Definition BaseNnumber.hpp:58
__host__ __device__ Integer shiftDigits(Integer const num, Integer const trans) const
Definition BaseNnumber.hpp:147
__host__ __device__ BaseConverter(BaseConverter< Integer > const &other)
Definition BaseNnumber.hpp:37
__host__ BaseConverter const & printInDigits(Integer const num) const
Definition BaseNnumber.hpp:240
__host__ BaseConverter const & printInDigits() const
Definition BaseNnumber.hpp:245
Integer m_max
Definition BaseNnumber.hpp:23
__host__ __device__ BaseConverter & setParam(Integer Base, Integer Length)
Set the base and the length of the positional notation to which the input number will converted.
Definition BaseNnumber.hpp:94
__host__ __device__ BaseConverter const & shiftDigits(Integer const trans) const
Definition BaseNnumber.hpp:151
__host__ __device__ Integer digit(Integer const num, Integer const pos, Integer const base, Integer const length) const
Returns the (pos)-th digit of the input (num) in given base and length.
Definition BaseNnumber.hpp:113
__host__ __device__ Integer digitsToNumber(Input const &digits) const
Definition BaseNnumber.hpp:176
__host__ __device__ Integer maxVal() const
Definition BaseNnumber.hpp:57
Integer m_length
Definition BaseNnumber.hpp:22
__host__ __device__ Integer base() const
Definition BaseNnumber.hpp:55
__host__ __device__ Integer digit(Integer const num, Integer const pos) const
Definition BaseNnumber.hpp:119
Integer m_base
Definition BaseNnumber.hpp:21
__host__ __device__ BaseConverter const & printInDigits(Output &output) const
Definition BaseNnumber.hpp:220
__host__ __device__ Integer shiftDigits(Integer const num, Integer const trans, Integer const base, Integer const length) const
Shifts a number (num) to right by (trans) in terms of the positional notation with given base and len...
Definition BaseNnumber.hpp:139
__host__ __device__ BaseConverter(Integer Base, Integer Length)
Construct a new BaseConverter object.
Definition BaseNnumber.hpp:34
__host__ __device__ Integer digit(Integer const pos) const
Definition BaseNnumber.hpp:122
__host__ __device__ BaseConverter const & set(Input num) const
Definition BaseNnumber.hpp:83
__host__ __device__ BaseConverter const & set(Input config) const
Definition BaseNnumber.hpp:72
__host__ __device__ Integer digitsToNumber(Input const &digits, Integer const base, Integer const length) const
Converts an array of integers to the corresponding integer in terms of the positional notation with g...
Definition BaseNnumber.hpp:166
__host__ __device__ Integer length() const
Definition BaseNnumber.hpp:56
Integer m_register
Definition BaseNnumber.hpp:24
__host__ void status(void) const
Show the status of the instance.
Definition BaseNnumber.hpp:47
__host__ __device__ BaseConverter()
Definition BaseNnumber.hpp:27
__host__ __device__ auto printInDigits(Output &output, Integer const num, Integer const base, Integer const length) const -> typename std::enable_if< std::is_integral< Output >::value==false, BaseConverter const & >::type
Expresses an integer (num) in the positional notation with given (base) and (length)
Definition BaseNnumber.hpp:191
__host__ __device__ auto printInDigits(Output &output, Integer const num) const -> typename std::enable_if< std::is_integral< Output >::value==false, BaseConverter const & >::type
Definition BaseNnumber.hpp:211
__host__ BaseConverter const & printInDigits(Integer const num, Integer const base, Integer const length) const
Definition BaseNnumber.hpp:226