19#ifndef HYPERCOMPLEX_HYPERCOMPLEX_MPFR_HPP_
20#define HYPERCOMPLEX_HYPERCOMPLEX_MPFR_HPP_
24static uint64_t MPFR_global_precision;
30 return MPFR_global_precision;
37 MPFR_global_precision = n;
44 assert(!mpfr_mp_memory_cleanup());
49template <const u
int64_t dim>
52 mpfr_t* arr =
new mpfr_t[dim];
53 static inline uint64_t** baseprodabs;
54 static inline bool** baseprodpos;
60 int64_t** M =
new int64_t*[dim];
61 for (uint64_t i = 0; i < dim; i++) M[i] =
new int64_t[dim];
65 for (uint64_t i=0; i < n; i++) {
66 for (uint64_t j=0; j < n; j++) {
67 M[i][n+j] = M[j][i] > 0 ? M[j][i] + n : M[j][i] - n;
68 M[i+n][j] = M[i][j] > 0 ? M[i][j] + n : M[i][j] - n;
69 M[i+n][j] = M[i+n][j] * (j ? -1 : 1);
70 M[i+n][j+n] = -M[j][i] * (j ? -1 : 1);
75 baseprodabs =
new uint64_t*[dim];
76 baseprodpos =
new bool*[dim];
77 for (uint64_t i = 0; i < dim; i++) {
78 baseprodabs[i] =
new uint64_t[dim];
79 baseprodpos[i] =
new bool[dim];
81 for (uint64_t i=0; i < dim; i++) {
82 for (uint64_t j=0; j < dim; j++) {
83 baseprodabs[i][j] = std::abs(M[i][j]) - 1;
84 baseprodpos[i][j] = (0 < M[i][j]);
87 for (uint64_t i = 0; i < dim; i++) {
96 for (uint64_t i = 0; i < dim; i++) {
97 delete[] baseprodabs[i];
98 delete[] baseprodpos[i];
100 delete[] baseprodabs;
101 delete[] baseprodpos;
114 mpfr_init2(prod, MPFR_global_precision);
116 for (uint64_t i=0; i < dim; i++)
117 mpfr_init2(temparr[i], MPFR_global_precision);
118 for (uint64_t i=0; i < dim; i++) mpfr_set_zero(temparr[i], 0);
119 for (uint64_t i=0; i < dim; i++) {
120 for (uint64_t j=0; j < dim; j++) {
121 mpfr_mul(prod, H1[i], H2[j], MPFR_RNDN);
122 if (Hypercomplex::baseprodpos[i][j]) {
124 temparr[Hypercomplex::baseprodabs[i][j]],
125 temparr[Hypercomplex::baseprodabs[i][j]],
130 temparr[Hypercomplex::baseprodabs[i][j]],
131 temparr[Hypercomplex::baseprodabs[i][j]],
138 for (uint64_t i=0; i < dim; i++) mpfr_clear(temparr[i]);
152 throw std::invalid_argument(
"invalid dimension");
154 if ((dim & (dim - 1)) != 0) {
156 throw std::invalid_argument(
"invalid dimension");
158 for (uint64_t i=0; i < dim; i++)
159 mpfr_init2(arr[i], MPFR_global_precision);
160 for (uint64_t i=0; i < dim; i++)
161 mpfr_set(arr[i], ARR[i], MPFR_RNDN);
171 for (uint64_t i=0; i < dim; i++)
172 mpfr_init2(arr[i], MPFR_global_precision);
173 for (uint64_t i=0; i < dim; i++)
174 mpfr_set(arr[i], H[i], MPFR_RNDN);
180 for (uint64_t i=0; i < dim; i++) mpfr_clear(arr[i]);
187 uint64_t
_()
const {
return dim; }
200 mpfr_init2(temp, MPFR_global_precision);
201 mpfr_set_zero(
norm, 0);
202 for (uint64_t i=0; i < dim; i++) {
203 mpfr_mul(temp, arr[i], arr[i], MPFR_RNDN);
204 mpfr_add(
norm,
norm, temp, MPFR_RNDN);
216 mpfr_init2(zero, MPFR_global_precision);
217 mpfr_init2(
norm, MPFR_global_precision);
218 mpfr_set_zero(zero, 0);
220 if (mpfr_equal_p(
norm, zero)) {
223 throw std::invalid_argument(
"division by zero");
226 for (uint64_t i=0; i < dim; i++)
227 mpfr_init2(temparr[i], MPFR_global_precision);
229 mpfr_div(temparr[0], arr[0],
norm, MPFR_RNDN);
230 for (uint64_t i=1; i < dim; i++) {
231 mpfr_div(temparr[i], arr[i],
norm, MPFR_RNDN);
232 mpfr_sub(temparr[i], zero, temparr[i], MPFR_RNDN);
237 for (uint64_t i=0; i < dim; i++) mpfr_clear(temparr[i]);
248 template <const u
int64_t newdim>
250 if (newdim <= dim)
throw std::invalid_argument(
"invalid dimension");
251 mpfr_t temparr[newdim];
252 for (uint64_t i=0; i < newdim; i++)
253 mpfr_init2(temparr[i], MPFR_global_precision);
254 for (uint64_t i=0; i < dim; i++)
255 mpfr_set(temparr[i], arr[i], MPFR_RNDN);
256 for (uint64_t i=dim; i < newdim; i++) mpfr_set_zero(temparr[i], 0);
258 for (uint64_t i=0; i < newdim; i++) mpfr_clear(temparr[i]);
267 mpfr_init2(zero, MPFR_global_precision);
268 mpfr_set_zero(zero, 0);
270 for (uint64_t i=0; i < dim; i++)
271 mpfr_init2(temparr[i], MPFR_global_precision);
272 mpfr_set(temparr[0], arr[0], MPFR_RNDN);
273 for (uint64_t i=1; i < dim; i++)
274 mpfr_sub(temparr[i], zero, arr[i], MPFR_RNDN);
276 for (uint64_t i=0; i < dim; i++) mpfr_clear(temparr[i]);
286 mpfr_init2(zero, MPFR_global_precision);
287 mpfr_set_zero(zero, 0);
289 for (uint64_t i=0; i < dim; i++)
290 mpfr_init2(temparr[i], MPFR_global_precision);
291 for (uint64_t i=0; i < dim; i++)
292 mpfr_sub(temparr[i], zero, arr[i], MPFR_RNDN);
294 for (uint64_t i=0; i < dim; i++) mpfr_clear(temparr[i]);
304 if (
this == &H)
return *
this;
305 for (uint64_t i=0; i < dim; i++)
306 mpfr_set(arr[i], H[i], MPFR_RNDN);
315 assert(0 <= i && i < dim);
324 assert(0 <= i && i < dim);
334 for (uint64_t i=0; i < dim; i++)
335 mpfr_set((*
this)[i], result[i], MPFR_RNDN);
345 for (uint64_t i=0; i < dim; i++)
346 mpfr_set((*
this)[i], result[i], MPFR_RNDN);
356 for (uint64_t i=0; i < dim; i++)
357 mpfr_set((*
this)[i], result[i], MPFR_RNDN);
367 for (uint64_t i=0; i < dim; i++)
368 mpfr_set((*
this)[i], result[i], MPFR_RNDN);
378 for (uint64_t i=0; i < dim; i++)
379 mpfr_set((*
this)[i], result[i], MPFR_RNDN);
389template <const u
int64_t dim>
394 for (uint64_t i=0; i < dim; i++) {
395 if (!mpfr_equal_p(H1[i], H2[i]))
return false;
405template <const u
int64_t dim>
418template <const u
int64_t dim>
424 for (uint64_t i=0; i < dim; i++)
425 mpfr_init2(temparr[i], MPFR_global_precision);
426 for (uint64_t i=0; i < dim; i++)
427 mpfr_add(temparr[i], H1[i], H2[i], MPFR_RNDN);
429 for (uint64_t i=0; i < dim; i++) mpfr_clear(temparr[i]);
438template <const u
int64_t dim>
444 for (uint64_t i=0; i < dim; i++)
445 mpfr_init2(temparr[i], MPFR_global_precision);
446 for (uint64_t i=0; i < dim; i++)
447 mpfr_sub(temparr[i], H1[i], H2[i], MPFR_RNDN);
449 for (uint64_t i=0; i < dim; i++) mpfr_clear(temparr[i]);
458template <const u
int64_t dim>
464 if constexpr (dim == 1) {
466 mpfr_init2(result, MPFR_global_precision);
467 mpfr_mul(result, H1[0], H2[0], MPFR_RNDN);
469 mpfr_init2(temparr[0], MPFR_global_precision);
470 mpfr_set(temparr[0], result, MPFR_RNDN);
473 mpfr_clear(temparr[0]);
478 const uint64_t halfd = dim / 2;
480 for (uint64_t i=0; i < dim; i++)
481 mpfr_init2(temparr[i], MPFR_global_precision);
483 for (uint64_t i=0; i < halfd; i++)
484 mpfr_set(temparr[i], H1[i], MPFR_RNDN);
486 for (uint64_t i=0; i < halfd; i++)
487 mpfr_set(temparr[i], H1[i+halfd], MPFR_RNDN);
489 for (uint64_t i=0; i < halfd; i++)
490 mpfr_set(temparr[i], H2[i], MPFR_RNDN);
492 for (uint64_t i=0; i < halfd; i++)
493 mpfr_set(temparr[i], H2[i+halfd], MPFR_RNDN);
503 for (uint64_t i=0; i < halfd; i++)
504 mpfr_set(temparr[i], Ha[i], MPFR_RNDN);
505 for (uint64_t i=0; i < halfd; i++)
506 mpfr_set(temparr[i+halfd], Hb[i], MPFR_RNDN);
508 for (uint64_t i=0; i < dim; i++) mpfr_clear(temparr[i]);
518template <const u
int64_t dim>
524 throw std::invalid_argument(
"zero is not a valid argument");
527 for (uint64_t i=0; i < x-1; i++) Hx *= H;
537template <const u
int64_t dim>
551template <const u
int64_t dim>
556 mpfr_exp_t exponent = 0;
558 for (uint64_t i=0; i < dim - 1; i++) {
559 outstr = mpfr_get_str(NULL, &exponent, 10, 0, H[i], MPFR_RNDN);
560 os << outstr <<
"E" << exponent <<
" ";
561 mpfr_free_str(outstr);
563 outstr = mpfr_get_str(NULL, &exponent, 10, 0, H[dim - 1], MPFR_RNDN);
564 os << outstr <<
"E" << exponent;
565 mpfr_free_str(outstr);
573template <const u
int64_t dim>
576 for (uint64_t i=1; i < dim; i++) mpfr_set_zero(result[i], 0);
584template <const u
int64_t dim>
587 mpfr_set_zero(result[0], 0);
595template <const u
int64_t dim>
598 mpfr_t zero, norm, expreal;
599 mpfr_init2(zero, MPFR_global_precision);
600 mpfr_init2(norm, MPFR_global_precision);
601 mpfr_init2(expreal, MPFR_global_precision);
602 mpfr_set_zero(zero, 0);
604 mpfr_exp(expreal, H[0], MPFR_RNDN);
606 if (mpfr_equal_p(norm, zero)) {
607 mpfr_set(result[0], expreal, MPFR_RNDN);
608 for (uint64_t i=1; i < dim; i++) mpfr_set_zero(result[i], 0);
611 mpfr_init2(sinv_v, MPFR_global_precision);
612 mpfr_sin(sinv_v, norm, MPFR_RNDN);
613 mpfr_div(sinv_v, sinv_v, norm, MPFR_RNDN);
614 for (uint64_t i=0; i < dim; i++) {
615 mpfr_mul(result[i], result[i], sinv_v, MPFR_RNDN);
617 mpfr_cos(norm, norm, MPFR_RNDN);
618 mpfr_add(result[0], result[0], norm, MPFR_RNDN);
619 for (uint64_t i=0; i < dim; i++) {
620 mpfr_mul(result[i], result[i], expreal, MPFR_RNDN);
std::ostream & operator<<(std::ostream &os, const Hypercomplex< mpfr_t, dim > &H)
Print operator.
Definition: Hypercomplex_MPFR.hpp:552
uint64_t get_mpfr_precision()
Getter for the global precision of the MPFR variables.
Definition: Hypercomplex_MPFR.hpp:29
Hypercomplex< mpfr_t, dim > Re(const Hypercomplex< mpfr_t, dim > &H)
Real part of a hypercomplex number.
Definition: Hypercomplex_MPFR.hpp:574
void clear_mpfr_memory()
Wrapper for MPFR memory cleanup.
Definition: Hypercomplex_MPFR.hpp:42
bool operator!=(const Hypercomplex< mpfr_t, dim > &H1, const Hypercomplex< mpfr_t, dim > &H2)
Inequality operator.
Definition: Hypercomplex_MPFR.hpp:406
bool operator==(const Hypercomplex< mpfr_t, dim > &H1, const Hypercomplex< mpfr_t, dim > &H2)
Equality operator.
Definition: Hypercomplex_MPFR.hpp:390
Hypercomplex< mpfr_t, dim > operator/(const Hypercomplex< mpfr_t, dim > &H1, const Hypercomplex< mpfr_t, dim > &H2)
Division operator.
Definition: Hypercomplex_MPFR.hpp:538
Hypercomplex< mpfr_t, dim > exp(const Hypercomplex< mpfr_t, dim > &H)
Exponentiation operation on a hypercomplex number.
Definition: Hypercomplex_MPFR.hpp:596
void set_mpfr_precision(uint64_t n)
Setter for the global precision of the MPFR variables.
Definition: Hypercomplex_MPFR.hpp:36
Hypercomplex< mpfr_t, dim > operator+(const Hypercomplex< mpfr_t, dim > &H1, const Hypercomplex< mpfr_t, dim > &H2)
Addition operator.
Definition: Hypercomplex_MPFR.hpp:419
Hypercomplex< mpfr_t, dim > Im(const Hypercomplex< mpfr_t, dim > &H)
Imaginary part of a hypercomplex number.
Definition: Hypercomplex_MPFR.hpp:585
Hypercomplex< mpfr_t, dim > operator-(const Hypercomplex< mpfr_t, dim > &H1, const Hypercomplex< mpfr_t, dim > &H2)
Subtraction operator.
Definition: Hypercomplex_MPFR.hpp:439
Hypercomplex< mpfr_t, dim > operator^(const Hypercomplex< mpfr_t, dim > &H, const uint64_t x)
Power operator.
Definition: Hypercomplex_MPFR.hpp:519
Hypercomplex< mpfr_t, dim > operator*(const Hypercomplex< mpfr_t, dim > &H1, const Hypercomplex< mpfr_t, dim > &H2)
Multiplication operator.
Definition: Hypercomplex_MPFR.hpp:459
static void clear()
Cleanup function: free all memory.
Definition: Hypercomplex_MPFR.hpp:95
Hypercomplex(const Hypercomplex &H)
This is the copy constructor.
Definition: Hypercomplex_MPFR.hpp:170
Hypercomplex inv() const
Calculate inverse of a given number.
Definition: Hypercomplex_MPFR.hpp:214
Hypercomplex(const mpfr_t *ARR)
This is the main constructor.
Definition: Hypercomplex_MPFR.hpp:149
Hypercomplex< mpfr_t, newdim > expand() const
Cast a number into a higher dimension.
Definition: Hypercomplex_MPFR.hpp:249
static Hypercomplex MUL(const Hypercomplex &H1, const Hypercomplex &H2)
Optimised multiplication function.
Definition: Hypercomplex_MPFR.hpp:109
static void init()
Basis multiplication table initialiser.
Definition: Hypercomplex_MPFR.hpp:59
int32_t norm(mpfr_t norm) const
Calculate Euclidean norm of a number.
Definition: Hypercomplex_MPFR.hpp:198
uint64_t _() const
Dimensionality getter.
Definition: Hypercomplex_MPFR.hpp:187
Definition: Hypercomplex.hpp:48
Hypercomplex & operator^=(const uint64_t x)
Power-Assignment operator.
Definition: Hypercomplex.hpp:608
Hypercomplex & operator+=(const Hypercomplex &H)
Addition-Assignment operator.
Definition: Hypercomplex.hpp:578
Hypercomplex operator~() const
Create a complex conjugate.
Definition: Hypercomplex.hpp:421
Hypercomplex & operator/=(const Hypercomplex &H)
Division-Assignment operator.
Definition: Hypercomplex.hpp:618
Hypercomplex & operator=(const Hypercomplex &H)
Assignment operator.
Definition: Hypercomplex.hpp:440
T norm() const
Calculate Euclidean norm of a number.
Definition: Hypercomplex.hpp:384
T const & operator[](const uint64_t i) const
Access operator (const)
Definition: Hypercomplex.hpp:453
Hypercomplex operator-() const
Create an additive inverse of a given number.
Definition: Hypercomplex.hpp:431
Hypercomplex & operator*=(const Hypercomplex &H)
Multiplication-Assignment operator.
Definition: Hypercomplex.hpp:598
Hypercomplex & operator-=(const Hypercomplex &H)
Subtraction-Assignment operator.
Definition: Hypercomplex.hpp:588
Hypercomplex inv() const
Calculate inverse of a given number.
Definition: Hypercomplex.hpp:392