glucat  0.8.4
clifford_algebra_imp.h
Go to the documentation of this file.
1 #ifndef _GLUCAT_CLIFFORD_ALGEBRA_IMP_H
2 #define _GLUCAT_CLIFFORD_ALGEBRA_IMP_H
3 /***************************************************************************
4  GluCat : Generic library of universal Clifford algebra templates
5  clifford_algebra_imp.h : Implement common Clifford algebra functions
6  -------------------
7  begin : Sun 2001-12-09
8  copyright : (C) 2001-2012 by Paul C. Leopardi
9  ***************************************************************************
10 
11  This library is free software: you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published
13  by the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  This library is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with this library. If not, see <http://www.gnu.org/licenses/>.
23 
24  ***************************************************************************
25  This library is based on a prototype written by Arvind Raja and was
26  licensed under the LGPL with permission of the author. See Arvind Raja,
27  "Object-oriented implementations of Clifford algebras in C++: a prototype",
28  in Ablamowicz, Lounesto and Parra (eds.)
29  "Clifford algebras with numeric and symbolic computations", Birkhauser, 1996.
30  ***************************************************************************
31  See also Arvind Raja's original header comments in glucat.h
32  ***************************************************************************/
33 
34 // References for algorithms:
35 // [AS]:
36 // Milton Abramowicz and Irene A. Stegun, "Handbook of mathematical functions",
37 // Dover 1972, first published 1965.
38 // [CHKL]:
39 // Sheung Hun Cheng, Nicholas J. Higham, Charles S. Kenney and Alan J. Laub,
40 // "Approximating the Logarithm of a Matrix to Specified Accuracy", 1999.
41 // ftp://ftp.ma.man.ac.uk/pub/narep/narep353.ps.gz
42 // [GL]:
43 // Gene H. Golub and Charles F. van Loan,
44 // "Matrix Computations", 3rd ed., Johns Hopkins UP, 1996.
45 // [GW]:
46 // C.F. Gerald and P.O. Wheatley, "Applied Numerical Analysis",
47 // 6th Edition, Addison-Wesley, 1999.
48 // [H]:
49 // Nicholas J. Higham
50 // "The Scaling and Squaring Method for the Matrix Exponential Revisited",
51 // SIAM Journal on Matrix Analysis and Applications,
52 // Vol. 26, Issue 4 (2005), pp. 1179-1193.
53 // [Z]:
54 // Doron Zeilberger, "PADE" (Maple code), 2002.
55 // http://www.math.rutgers.edu/~zeilberg/tokhniot/PADE
56 
58 
59 #include <glucat/scalar.h>
60 
61 namespace glucat
62 {
63  template< typename Scalar_T, typename Index_Set_T, typename Multivector_T>
64  const std::string
66  classname()
67  { return "clifford_algebra"; }
68 
70  template
71  <
72  template<typename, const index_t, const index_t> class Multivector,
73  template<typename, const index_t, const index_t> class RHS,
74  typename Scalar_T, const index_t LO, const index_t HI
75  >
76  inline
77  bool
78  operator!= (const Multivector<Scalar_T,LO,HI>& lhs, const RHS<Scalar_T,LO,HI>& rhs)
79  { return !(lhs == rhs); }
80 
82  template< template<typename, const index_t, const index_t> class Multivector,
83  typename Scalar_T, const index_t LO, const index_t HI >
84  inline
85  bool
86  operator!= (const Multivector<Scalar_T,LO,HI>& lhs, const Scalar_T& scr)
87  { return !(lhs == scr); }
88 
90  template< template<typename, const index_t, const index_t> class Multivector,
91  typename Scalar_T, const index_t LO, const index_t HI >
92  inline
93  bool
94  operator!= (const Scalar_T& scr, const Multivector<Scalar_T,LO,HI>& rhs)
95  { return !(rhs == scr); }
96 
98  template< template<typename, const index_t, const index_t> class Multivector,
99  typename Scalar_T, const index_t LO, const index_t HI >
100  inline
101  const Multivector<Scalar_T,LO,HI>
102  operator+ (const Multivector<Scalar_T,LO,HI>& lhs, const Scalar_T& scr)
103  {
104  Multivector<Scalar_T,LO,HI> result = lhs;
105  return result += scr;
106  }
107 
109  template< template<typename, const index_t, const index_t> class Multivector,
110  typename Scalar_T, const index_t LO, const index_t HI >
111  inline
112  const Multivector<Scalar_T,LO,HI>
113  operator+ (const Scalar_T& scr, const Multivector<Scalar_T,LO,HI>& rhs)
114  {
115  return rhs + scr;
116  }
117 
119  template
120  <
121  template<typename, const index_t, const index_t> class Multivector,
122  template<typename, const index_t, const index_t> class RHS,
123  typename Scalar_T, const index_t LO, const index_t HI
124  >
125  inline
126  const Multivector<Scalar_T,LO,HI>
127  operator+ (const Multivector<Scalar_T,LO,HI>& lhs, const RHS<Scalar_T,LO,HI>& rhs)
128  {
129  Multivector<Scalar_T,LO,HI> result = lhs;
130  return result += rhs;
131  }
132 
134  template< template<typename, const index_t, const index_t> class Multivector,
135  typename Scalar_T, const index_t LO, const index_t HI >
136  inline
137  const Multivector<Scalar_T,LO,HI>
138  operator- (const Multivector<Scalar_T,LO,HI>& lhs, const Scalar_T& scr)
139  {
140  Multivector<Scalar_T,LO,HI> result = lhs;
141  return result += -scr;
142  }
143 
145  template< template<typename, const index_t, const index_t> class Multivector,
146  typename Scalar_T, const index_t LO, const index_t HI >
147  inline
148  const Multivector<Scalar_T,LO,HI>
149  operator- (const Scalar_T& scr, const Multivector<Scalar_T,LO,HI>& rhs)
150  { return -rhs + scr; }
151 
153  template
154  <
155  template<typename, const index_t, const index_t> class Multivector,
156  template<typename, const index_t, const index_t> class RHS,
157  typename Scalar_T, const index_t LO, const index_t HI
158  >
159  inline
160  const Multivector<Scalar_T,LO,HI>
161  operator- (const Multivector<Scalar_T,LO,HI>& lhs, const RHS<Scalar_T,LO,HI>& rhs)
162  {
163  Multivector<Scalar_T,LO,HI> result = lhs;
164  return result -= rhs;
165  }
166 
168  template< template<typename, const index_t, const index_t> class Multivector,
169  typename Scalar_T, const index_t LO, const index_t HI >
170  inline
171  const Multivector<Scalar_T,LO,HI>
172  operator* (const Multivector<Scalar_T,LO,HI>& lhs, const Scalar_T& scr)
173  {
174  Multivector<Scalar_T,LO,HI> result = lhs;
175  return result *= scr;
176  }
177 
179  template< template<typename, const index_t, const index_t> class Multivector,
180  typename Scalar_T, const index_t LO, const index_t HI >
181  inline
182  const Multivector<Scalar_T,LO,HI>
183  operator* (const Scalar_T& scr, const Multivector<Scalar_T,LO,HI>& rhs)
184  { // Note: this assumes that scalar commutes with multivector.
185  // This excludes Clifford algebras over non-commuting rings.
186  return rhs * scr;
187  }
188 
190  template
191  <
192  template<typename, const index_t, const index_t> class Multivector,
193  template<typename, const index_t, const index_t> class RHS,
194  typename Scalar_T, const index_t LO, const index_t HI
195  >
196  inline
197  const Multivector<Scalar_T,LO,HI>
198  operator* (const Multivector<Scalar_T,LO,HI>& lhs, const RHS<Scalar_T,LO,HI>& rhs)
199  {
200  typedef Multivector<Scalar_T,LO,HI> multivector_t;
201  return lhs * multivector_t(rhs);
202  }
203 
205  template
206  <
207  template<typename, const index_t, const index_t> class Multivector,
208  template<typename, const index_t, const index_t> class RHS,
209  typename Scalar_T, const index_t LO, const index_t HI
210  >
211  inline
212  const Multivector<Scalar_T,LO,HI>
213  operator^ (const Multivector<Scalar_T,LO,HI>& lhs, const RHS<Scalar_T,LO,HI>& rhs)
214  {
215  typedef Multivector<Scalar_T,LO,HI> multivector_t;
216  return lhs ^ multivector_t(rhs);
217  }
218 
220  template
221  <
222  template<typename, const index_t, const index_t> class Multivector,
223  template<typename, const index_t, const index_t> class RHS,
224  typename Scalar_T, const index_t LO, const index_t HI
225  >
226  inline
227  const Multivector<Scalar_T,LO,HI>
228  operator& (const Multivector<Scalar_T,LO,HI>& lhs, const RHS<Scalar_T,LO,HI>& rhs)
229  {
230  typedef Multivector<Scalar_T,LO,HI> multivector_t;
231  return lhs & multivector_t(rhs);
232  }
233 
235  template
236  <
237  template<typename, const index_t, const index_t> class Multivector,
238  template<typename, const index_t, const index_t> class RHS,
239  typename Scalar_T, const index_t LO, const index_t HI
240  >
241  inline
242  const Multivector<Scalar_T,LO,HI>
243  operator% (const Multivector<Scalar_T,LO,HI>& lhs, const RHS<Scalar_T,LO,HI>& rhs)
244  {
245  typedef Multivector<Scalar_T,LO,HI> multivector_t;
246  return lhs % multivector_t(rhs);
247  }
248 
250  template
251  <
252  template<typename, const index_t, const index_t> class Multivector,
253  template<typename, const index_t, const index_t> class RHS,
254  typename Scalar_T, const index_t LO, const index_t HI
255  >
256  inline
257  Scalar_T
258  star (const Multivector<Scalar_T,LO,HI>& lhs, const RHS<Scalar_T,LO,HI>& rhs)
259  {
260  typedef Multivector<Scalar_T,LO,HI> multivector_t;
261  return star(lhs, multivector_t(rhs));
262  }
263 
265  template< template<typename, const index_t, const index_t> class Multivector,
266  typename Scalar_T, const index_t LO, const index_t HI >
267  inline
268  const Multivector<Scalar_T,LO,HI>
269  operator/ (const Multivector<Scalar_T,LO,HI>& lhs, const Scalar_T& scr)
270  {
271  Multivector<Scalar_T,LO,HI> result = lhs;
272  return result /= scr;
273  }
274 
276  template< template<typename, const index_t, const index_t> class Multivector,
277  typename Scalar_T, const index_t LO, const index_t HI >
278  inline
279  const Multivector<Scalar_T,LO,HI>
280  operator/ (const Scalar_T& scr, const Multivector<Scalar_T,LO,HI>& rhs)
281  {
282  Multivector<Scalar_T,LO,HI> result = scr;
283  return result /= rhs;
284  }
285 
287  template
288  <
289  template<typename, const index_t, const index_t> class Multivector,
290  template<typename, const index_t, const index_t> class RHS,
291  typename Scalar_T, const index_t LO, const index_t HI
292  >
293  inline
294  const Multivector<Scalar_T,LO,HI>
295  operator/ (const Multivector<Scalar_T,LO,HI>& lhs, const RHS<Scalar_T,LO,HI>& rhs)
296  {
297  typedef Multivector<Scalar_T,LO,HI> multivector_t;
298  return lhs / multivector_t(rhs);
299  }
300 
302  template
303  <
304  template<typename, const index_t, const index_t> class Multivector,
305  template<typename, const index_t, const index_t> class RHS,
306  typename Scalar_T, const index_t LO, const index_t HI
307  >
308  inline
309  const Multivector<Scalar_T,LO,HI>
310  operator| (const Multivector<Scalar_T,LO,HI>& lhs, const RHS<Scalar_T,LO,HI>& rhs)
311  {
312  typedef Multivector<Scalar_T,LO,HI> multivector_t;
313  return lhs | multivector_t(rhs);
314  }
315 
317  template< template<typename, const index_t, const index_t> class Multivector,
318  typename Scalar_T, const index_t LO, const index_t HI >
319  inline
320  const Multivector<Scalar_T,LO,HI>
321  inv(const Multivector<Scalar_T,LO,HI>& val)
322  { return val.inv(); }
323 
325  template< template<typename, const index_t, const index_t> class Multivector,
326  typename Scalar_T, const index_t LO, const index_t HI >
327  const Multivector<Scalar_T,LO,HI>
328  pow(const Multivector<Scalar_T,LO,HI>& lhs, int rhs)
329  {
330  typedef Multivector<Scalar_T,LO,HI> multivector_t;
331  typedef numeric_traits<Scalar_T> traits_t;
332 
333  multivector_t a;
334  if (rhs < 0)
335  {
336  if (lhs == Scalar_T(0))
337  return traits_t::NaN();
338  rhs = -rhs;
339  a = lhs.inv();
340  }
341  else
342  a = lhs;
343  multivector_t result = Scalar_T(1);
344  for (;
345  rhs != 0;
346  rhs >>= 1, a *= a)
347  if (rhs & 1)
348  result *= a;
349  return result;
350  }
351 
353  template
354  <
355  template<typename, const index_t, const index_t> class Multivector,
356  template<typename, const index_t, const index_t> class RHS,
357  typename Scalar_T, const index_t LO, const index_t HI
358  >
359  inline
360  const Multivector<Scalar_T,LO,HI>
361  pow(const Multivector<Scalar_T,LO,HI>& lhs, const RHS<Scalar_T,LO,HI>& rhs)
362  {
363  typedef numeric_traits<Scalar_T> traits_t;
364 
365  if (lhs == Scalar_T(0))
366  {
367  const Scalar_T m = rhs.scalar();
368  if (rhs == m)
369  return (m < 0)
370  ? traits_t::NaN()
371  : (m == 0)
372  ? Scalar_T(1)
373  : Scalar_T(0);
374  else
375  return Scalar_T(0);
376  }
377  return exp(log(lhs) * rhs);
378  }
379 
381  template< template<typename, const index_t, const index_t> class Multivector,
382  typename Scalar_T, const index_t LO, const index_t HI >
383  const Multivector<Scalar_T,LO,HI>
384  outer_pow(const Multivector<Scalar_T,LO,HI>& lhs, int rhs)
385  { return lhs.outer_pow(rhs); }
386 
388  template< template<typename, const index_t, const index_t> class Multivector,
389  typename Scalar_T, const index_t LO, const index_t HI >
390  inline
391  Scalar_T
392  scalar(const Multivector<Scalar_T,LO,HI>& val)
393  { return val.scalar(); }
394 
396  template< template<typename, const index_t, const index_t> class Multivector,
397  typename Scalar_T, const index_t LO, const index_t HI >
398  inline
399  Scalar_T
400  real(const Multivector<Scalar_T,LO,HI>& val)
401  { return val.scalar(); }
402 
404  template
405  <
406  template<typename, const index_t, const index_t> class Multivector,
407  typename Scalar_T, const index_t LO, const index_t HI
408  >
409  inline
410  Scalar_T
411  imag(const Multivector<Scalar_T,LO,HI>& val)
412  { return Scalar_T(0); }
413 
415  template< template<typename, const index_t, const index_t> class Multivector,
416  typename Scalar_T, const index_t LO, const index_t HI >
417  inline
418  const Multivector<Scalar_T,LO,HI>
419  pure(const Multivector<Scalar_T,LO,HI>& val)
420  { return val - val.scalar(); }
421 
423  template< template<typename, const index_t, const index_t> class Multivector,
424  typename Scalar_T, const index_t LO, const index_t HI >
425  inline
426  const Multivector<Scalar_T,LO,HI>
427  even(const Multivector<Scalar_T,LO,HI>& val)
428  { return val.even(); }
429 
431  template< template<typename, const index_t, const index_t> class Multivector,
432  typename Scalar_T, const index_t LO, const index_t HI >
433  inline
434  const Multivector<Scalar_T,LO,HI>
435  odd(const Multivector<Scalar_T,LO,HI>& val)
436  { return val.odd(); }
437 
439  template< template<typename, const index_t, const index_t> class Multivector,
440  typename Scalar_T, const index_t LO, const index_t HI >
441  inline
442  const std::vector<Scalar_T>
443  vector_part(const Multivector<Scalar_T,LO,HI>& val)
444  { return val.vector_part(); }
445 
447  template< template<typename, const index_t, const index_t> class Multivector,
448  typename Scalar_T, const index_t LO, const index_t HI >
449  inline
450  const Multivector<Scalar_T,LO,HI>
451  involute(const Multivector<Scalar_T,LO,HI>& val)
452  { return val.involute(); }
453 
455  template< template<typename, const index_t, const index_t> class Multivector,
456  typename Scalar_T, const index_t LO, const index_t HI >
457  inline
458  const Multivector<Scalar_T,LO,HI>
459  reverse(const Multivector<Scalar_T,LO,HI>& val)
460  { return val.reverse(); }
461 
463  template< template<typename, const index_t, const index_t> class Multivector,
464  typename Scalar_T, const index_t LO, const index_t HI >
465  inline
466  const Multivector<Scalar_T,LO,HI>
467  conj(const Multivector<Scalar_T,LO,HI>& val)
468  { return val.conj(); }
469 
471  template< template<typename, const index_t, const index_t> class Multivector,
472  typename Scalar_T, const index_t LO, const index_t HI >
473  inline
474  Scalar_T
475  quad(const Multivector<Scalar_T,LO,HI>& val)
476  { return val.quad(); }
477 
479  template< template<typename, const index_t, const index_t> class Multivector,
480  typename Scalar_T, const index_t LO, const index_t HI >
481  inline
482  Scalar_T
483  norm(const Multivector<Scalar_T,LO,HI>& val)
484  { return val.norm(); }
485 
487  template< template<typename, const index_t, const index_t> class Multivector,
488  typename Scalar_T, const index_t LO, const index_t HI >
489  inline
490  Scalar_T
491  abs(const Multivector<Scalar_T,LO,HI>& val)
492  { return numeric_traits<Scalar_T>::sqrt(val.norm()); }
493 
495  template< template<typename, const index_t, const index_t> class Multivector,
496  typename Scalar_T, const index_t LO, const index_t HI >
497  inline
498  Scalar_T
499  max_abs(const Multivector<Scalar_T,LO,HI>& val)
500  { return val.max_abs(); }
501 
503  template< template<typename, const index_t, const index_t> class Multivector,
504  typename Scalar_T, const index_t LO, const index_t HI >
505  const Multivector<Scalar_T,LO,HI>
506  complexifier(const Multivector<Scalar_T,LO,HI>& val)
507  {
508  typedef Multivector<Scalar_T,LO,HI> multivector_t;
509  typedef numeric_traits<Scalar_T> traits_t;
510  typedef typename multivector_t::index_set_t index_set_t;
511 
512  index_set_t frm = val.frame();
513  index_t incp[] = {0, 2, 1, 0};
514  index_t incq[] = {1, 0, 0, 0};
515  index_t bott = pos_mod((frm.count_pos() - frm.count_neg()), 4);
516  for (index_t
517  k = 0;
518  k != incp[bott];
519  k++)
520  for (index_t
521  idx = 1;
522  idx != HI+1;
523  ++idx)
524  if (!frm[idx])
525  {
526  frm.set(idx);
527  break;
528  }
529  for (index_t
530  k = 0;
531  k != incq[bott];
532  k++)
533  for (index_t
534  idx = -1;
535  idx != LO-1;
536  --idx)
537  if (!frm[idx])
538  {
539  frm.set(idx);
540  break;
541  }
542  index_t new_bott = pos_mod(frm.count_pos() - frm.count_neg(), 4);
543 
544  if ((incp[new_bott] == 0) && (incq[new_bott] == 0))
545  return multivector_t(frm, Scalar_T(1));
546  else
547  // Return IEEE NaN or -Inf
548  return traits_t::NaN();
549  }
550 
553  template< template<typename, const index_t, const index_t> class Multivector,
554  typename Scalar_T, const index_t LO, const index_t HI >
555  inline
556  const Multivector<Scalar_T,LO,HI>
557  elliptic(const Multivector<Scalar_T,LO,HI>& val)
558  { return complexifier(val); }
559 
561  template< template<typename, const index_t, const index_t> class Multivector,
562  typename Scalar_T, const index_t LO, const index_t HI >
563  inline
564  static
565  void
566  check_complex(const Multivector<Scalar_T,LO,HI>& val,
567  const Multivector<Scalar_T,LO,HI>& i, const bool prechecked = false)
568  {
569  if (!prechecked)
570  {
571  typedef Multivector<Scalar_T,LO,HI> multivector_t;
572  typedef typename multivector_t::index_set_t index_set_t;
573  typedef typename multivector_t::error_t error_t;
574 
575  const index_set_t i_frame = i.frame();
576  // We need i to be a complexifier whose frame is large enough to represent val
577  if (complexifier(i) != i ||
578  (val.frame() | i_frame) != i_frame ||
579  complexifier(val).frame().count() > i_frame.count())
580  throw error_t("check_complex(val, i): i is not a valid complexifier for val");
581  }
582  }
583 
585  template< template<typename, const index_t, const index_t> class Multivector,
586  typename Scalar_T, const index_t LO, const index_t HI >
587  inline
588  const Multivector<Scalar_T,LO,HI>
589  sqrt(const Multivector<Scalar_T,LO,HI>& val, const Multivector<Scalar_T,LO,HI>& i, bool prechecked)
590  { return sqrt(val, i, prechecked); }
591 
593  template< template<typename, const index_t, const index_t> class Multivector,
594  typename Scalar_T, const index_t LO, const index_t HI >
595  inline
596  const Multivector<Scalar_T,LO,HI>
597  sqrt(const Multivector<Scalar_T,LO,HI>& val)
598  { return sqrt(val, complexifier(val), true); }
599 
601  template< template<typename, const index_t, const index_t> class Multivector,
602  typename Scalar_T, const index_t LO, const index_t HI >
603  const Multivector<Scalar_T,LO,HI>
604  clifford_exp(const Multivector<Scalar_T,LO,HI>& val)
605  {
606  // Scaling and squaring Pade' approximation of matrix exponential
607  // Reference: [GL], Section 11.3, p572-576
608  // Reference: [H]
609 
610  typedef numeric_traits<Scalar_T> traits_t;
611 
612  const Scalar_T scalar_val = scalar(val);
613  const Scalar_T scalar_exp = traits_t::exp(scalar_val);
614  if (traits_t::isNaN_or_isInf(scalar_exp))
615  return traits_t::NaN();
616  if (val == scalar_val)
617  return scalar_exp;
618 
619  typedef Multivector<Scalar_T,LO,HI> multivector_t;
620  multivector_t A = val - scalar_val;
621  const Scalar_T pure_scale2 = A.norm();
622 
623  if (traits_t::isNaN_or_isInf(pure_scale2))
624  return traits_t::NaN();
625  if (pure_scale2 == Scalar_T(0))
626  return scalar_exp;
627 
628  const int ilog2_scale =
629  std::max(0, traits_t::to_int(ceil((log2(pure_scale2) + Scalar_T(A.frame().count()))/Scalar_T(2))) - 3);
630  const Scalar_T i_scale = traits_t::pow(Scalar_T(2), ilog2_scale);
631  if (traits_t::isNaN_or_isInf(i_scale))
632  return traits_t::NaN();
633 
634  A /= i_scale;
635  multivector_t pure_exp;
636  {
637  typedef std::numeric_limits<Scalar_T> limits_t;
638  const int nbr_even_powers = 2*(limits_t::digits / 32) + 4;
639 
640  // Create an array of coefficients
641  const int max_power = 2*nbr_even_powers + 1;
642  static Scalar_T c[max_power+1];
643  if (c[0] != Scalar_T(1))
644  {
645  c[0] = Scalar_T(1);
646  for (int
647  k = 0;
648  k != max_power;
649  ++k)
650  c[k+1] = c[k]*(max_power-k) / ((2*max_power-k)*(k+1));
651  }
652 
653  // Create an array of even powers
654  multivector_t AA[nbr_even_powers];
655  AA[0] = A * A;
656  AA[1] = AA[0] * AA[0];
657  for (int
658  k = 2;
659  k != nbr_even_powers;
660  ++k)
661  AA[k] = AA[k-2] * AA[1];
662 
663  // Use compensated summation to calculate U and AV
664  multivector_t residual = 0;
665  multivector_t U = c[0];
666  for (int
667  k = 0;
668  k != nbr_even_powers;
669  ++k)
670  {
671  const multivector_t& term = AA[k]*c[2*k + 2] - residual;
672  const multivector_t& sum = U + term;
673  residual = (sum - U) - term;
674  U = sum;
675  }
676  residual = 0;
677  multivector_t AV = c[1];
678  for (int
679  k = 0;
680  k != nbr_even_powers;
681  ++k)
682  {
683  const multivector_t& term = AA[k]*c[2*k + 3] - residual;
684  const multivector_t& sum = AV + term;
685  residual = (sum - AV) - term;
686  AV = sum;
687  }
688  AV *= A;
689  pure_exp = (U+AV) / (U-AV);
690  }
691  for (int
692  k = 0;
693  k != ilog2_scale;
694  ++k)
695  pure_exp *= pure_exp;
696  return pure_exp * scalar_exp;
697  }
698 
700  template< template<typename, const index_t, const index_t> class Multivector,
701  typename Scalar_T, const index_t LO, const index_t HI >
702  inline
703  const Multivector<Scalar_T,LO,HI>
704  log(const Multivector<Scalar_T,LO,HI>& val, const Multivector<Scalar_T,LO,HI>& i, bool prechecked)
705  { return log(val, i, prechecked); }
706 
708  template< template<typename, const index_t, const index_t> class Multivector,
709  typename Scalar_T, const index_t LO, const index_t HI >
710  inline
711  const Multivector<Scalar_T,LO,HI>
712  log(const Multivector<Scalar_T,LO,HI>& val)
713  { return log(val, complexifier(val), true); }
714 
716  template< template<typename, const index_t, const index_t> class Multivector,
717  typename Scalar_T, const index_t LO, const index_t HI >
718  inline
719  const Multivector<Scalar_T,LO,HI>
720  cosh(const Multivector<Scalar_T,LO,HI>& val)
721  {
722  typedef numeric_traits<Scalar_T> traits_t;
723  if (val.isnan())
724  return traits_t::NaN();
725 
726  const Scalar_T& s = scalar(val);
727  if (val == s)
728  return traits_t::cosh(s);
729  return (exp(val)+exp(-val)) / Scalar_T(2);
730  }
731 
733  // Reference: [AS], Section 4.6, p86-89
734  template< template<typename, const index_t, const index_t> class Multivector,
735  typename Scalar_T, const index_t LO, const index_t HI >
736  inline
737  const Multivector<Scalar_T,LO,HI>
738  acosh(const Multivector<Scalar_T,LO,HI>& val, const Multivector<Scalar_T,LO,HI>& i, bool prechecked)
739  {
740  typedef numeric_traits<Scalar_T> traits_t;
741  check_complex(val, i, prechecked);
742  if (val.isnan())
743  return traits_t::NaN();
744 
745  typedef Multivector<Scalar_T,LO,HI> multivector_t;
746  const multivector_t radical = sqrt(val*val - Scalar_T(1), i, true);
747  return (norm(val + radical) >= norm(val))
748  ? log(val + radical, i, true)
749  : -log(val - radical, i, true);
750  }
751 
753  // Reference: [AS], Section 4.6, p86-89
754  template< template<typename, const index_t, const index_t> class Multivector,
755  typename Scalar_T, const index_t LO, const index_t HI >
756  inline
757  const Multivector<Scalar_T,LO,HI>
758  acosh(const Multivector<Scalar_T,LO,HI>& val)
759  { return acosh(val, complexifier(val), true); }
760 
762  template< template<typename, const index_t, const index_t> class Multivector,
763  typename Scalar_T, const index_t LO, const index_t HI >
764  const Multivector<Scalar_T,LO,HI>
765  cos(const Multivector<Scalar_T,LO,HI>& val, const Multivector<Scalar_T,LO,HI>& i, bool prechecked)
766  {
767  typedef numeric_traits<Scalar_T> traits_t;
768  if (val.isnan())
769  return traits_t::NaN();
770 
771  const Scalar_T& s = scalar(val);
772  if (val == s)
773  return traits_t::cos(s);
774 
775  check_complex(val, i, prechecked);
776 
777  typedef Multivector<Scalar_T,LO,HI> multivector_t;
778  static const Scalar_T& twopi = Scalar_T(2) * traits_t::pi();
779  const multivector_t& z = i *
780  (val - s + traits_t::fmod(s, twopi));
781  return (exp(z)+exp(-z)) / Scalar_T(2);
782  }
783 
785  template< template<typename, const index_t, const index_t> class Multivector,
786  typename Scalar_T, const index_t LO, const index_t HI >
787  inline
788  const Multivector<Scalar_T,LO,HI>
789  cos(const Multivector<Scalar_T,LO,HI>& val)
790  { return cos(val, complexifier(val), true); }
791 
793  // Reference: [AS], Section 4.4, p79-83
794  template< template<typename, const index_t, const index_t> class Multivector,
795  typename Scalar_T, const index_t LO, const index_t HI >
796  inline
797  const Multivector<Scalar_T,LO,HI>
798  acos(const Multivector<Scalar_T,LO,HI>& val, const Multivector<Scalar_T,LO,HI>& i, bool prechecked)
799  {
800  typedef numeric_traits<Scalar_T> traits_t;
801  if (val.isnan())
802  return traits_t::NaN();
803 
804  const Scalar_T& realval = val.scalar();
805  if (val == realval && traits_t::abs(realval) <= Scalar_T(1))
806  return traits_t::acos(realval);
807 
808  check_complex(val, i, prechecked);
809  return i * acosh(val, i, true);
810  }
811 
813  // Reference: [AS], Section 4.4, p79-83
814  template< template<typename, const index_t, const index_t> class Multivector,
815  typename Scalar_T, const index_t LO, const index_t HI >
816  inline
817  const Multivector<Scalar_T,LO,HI>
818  acos(const Multivector<Scalar_T,LO,HI>& val)
819  { return acos(val, complexifier(val), true); }
820 
822  template< template<typename, const index_t, const index_t> class Multivector,
823  typename Scalar_T, const index_t LO, const index_t HI >
824  inline
825  const Multivector<Scalar_T,LO,HI>
826  sinh(const Multivector<Scalar_T,LO,HI>& val)
827  {
828  typedef numeric_traits<Scalar_T> traits_t;
829  if (val.isnan())
830  return traits_t::NaN();
831 
832  const Scalar_T& s = scalar(val);
833  if (val == s)
834  return traits_t::sinh(s);
835 
836  return (exp(val)-exp(-val)) / Scalar_T(2);
837  }
838 
840  // Reference: [AS], Section 4.6, p86-89
841  template< template<typename, const index_t, const index_t> class Multivector,
842  typename Scalar_T, const index_t LO, const index_t HI >
843  inline
844  const Multivector<Scalar_T,LO,HI>
845  asinh(const Multivector<Scalar_T,LO,HI>& val, const Multivector<Scalar_T,LO,HI>& i, bool prechecked)
846  {
847  typedef numeric_traits<Scalar_T> traits_t;
848  check_complex(val, i, prechecked);
849  if (val.isnan())
850  return traits_t::NaN();
851 
852  typedef Multivector<Scalar_T,LO,HI> multivector_t;
853  const multivector_t radical = sqrt(val*val + Scalar_T(1), i, true);
854  return (norm(val + radical) >= norm(val))
855  ? log( val + radical, i, true)
856  : -log(-val + radical, i, true);
857  }
858 
860  // Reference: [AS], Section 4.6, p86-89
861  template< template<typename, const index_t, const index_t> class Multivector,
862  typename Scalar_T, const index_t LO, const index_t HI >
863  inline
864  const Multivector<Scalar_T,LO,HI>
865  asinh(const Multivector<Scalar_T,LO,HI>& val)
866  { return asinh(val, complexifier(val), true); }
867 
869  template< template<typename, const index_t, const index_t> class Multivector,
870  typename Scalar_T, const index_t LO, const index_t HI >
871  const Multivector<Scalar_T,LO,HI>
872  sin(const Multivector<Scalar_T,LO,HI>& val, const Multivector<Scalar_T,LO,HI>& i, bool prechecked)
873  {
874  typedef numeric_traits<Scalar_T> traits_t;
875  if (val.isnan())
876  return traits_t::NaN();
877 
878  const Scalar_T& s = scalar(val);
879  if (val == s)
880  return traits_t::sin(s);
881 
882  check_complex(val, i, prechecked);
883 
884  typedef Multivector<Scalar_T,LO,HI> multivector_t;
885  static const Scalar_T& twopi = Scalar_T(2) * traits_t::pi();
886  const multivector_t& z = i *
887  (val - s + traits_t::fmod(s, twopi));
888  return i * (exp(-z)-exp(z)) / Scalar_T(2);
889  }
890 
892  template< template<typename, const index_t, const index_t> class Multivector,
893  typename Scalar_T, const index_t LO, const index_t HI >
894  inline
895  const Multivector<Scalar_T,LO,HI>
896  sin(const Multivector<Scalar_T,LO,HI>& val)
897  { return sin(val, complexifier(val), true); }
898 
900  // Reference: [AS], Section 4.4, p79-83
901  template< template<typename, const index_t, const index_t> class Multivector,
902  typename Scalar_T, const index_t LO, const index_t HI >
903  inline
904  const Multivector<Scalar_T,LO,HI>
905  asin(const Multivector<Scalar_T,LO,HI>& val, const Multivector<Scalar_T,LO,HI>& i, bool prechecked)
906  {
907  typedef numeric_traits<Scalar_T> traits_t;
908  if (val.isnan())
909  return traits_t::NaN();
910 
911  const Scalar_T& realval = val.scalar();
912  if (val == realval && traits_t::abs(realval) <= Scalar_T(1))
913  return traits_t::asin(realval);
914 
915  check_complex(val, i, prechecked);
916  return -i * asinh(i * val, i, true);
917  }
918 
920  // Reference: [AS], Section 4.4, p79-83
921  template< template<typename, const index_t, const index_t> class Multivector,
922  typename Scalar_T, const index_t LO, const index_t HI >
923  inline
924  const Multivector<Scalar_T,LO,HI>
925  asin(const Multivector<Scalar_T,LO,HI>& val)
926  { return asin(val, complexifier(val), true); }
927 
929  template< template<typename, const index_t, const index_t> class Multivector,
930  typename Scalar_T, const index_t LO, const index_t HI >
931  inline
932  const Multivector<Scalar_T,LO,HI>
933  tanh(const Multivector<Scalar_T,LO,HI>& val)
934  {
935  typedef numeric_traits<Scalar_T> traits_t;
936  if (val.isnan())
937  return traits_t::NaN();
938 
939  const Scalar_T& s = scalar(val);
940  if (val == s)
941  return traits_t::tanh(s);
942 
943  return sinh(val) / cosh(val);
944  }
945 
947  // Reference: [AS], Section 4.6, p86-89
948  template< template<typename, const index_t, const index_t> class Multivector,
949  typename Scalar_T, const index_t LO, const index_t HI >
950  inline
951  const Multivector<Scalar_T,LO,HI>
952  atanh(const Multivector<Scalar_T,LO,HI>& val, const Multivector<Scalar_T,LO,HI>& i, bool prechecked)
953  {
954  typedef numeric_traits<Scalar_T> traits_t;
955  check_complex(val, i, prechecked);
956  return val.isnan()
957  ? traits_t::NaN()
958  : (norm(val + Scalar_T(1)) > norm(val - Scalar_T(1)))
959  ? (log(val + Scalar_T(1), i, true) - log(-val + Scalar_T(1), i, true)) / Scalar_T(2)
960  : log((val + Scalar_T(1)) / (-val + Scalar_T(1)), i, true) / Scalar_T(2);
961  }
962 
964  // Reference: [AS], Section 4.6, p86-89
965  template< template<typename, const index_t, const index_t> class Multivector,
966  typename Scalar_T, const index_t LO, const index_t HI >
967  inline
968  const Multivector<Scalar_T,LO,HI>
969  atanh(const Multivector<Scalar_T,LO,HI>& val)
970  { return atanh(val, complexifier(val), true); }
971 
973  template< template<typename, const index_t, const index_t> class Multivector,
974  typename Scalar_T, const index_t LO, const index_t HI >
975  inline
976  const Multivector<Scalar_T,LO,HI>
977  tan(const Multivector<Scalar_T,LO,HI>& val, const Multivector<Scalar_T,LO,HI>& i, bool prechecked)
978  {
979  typedef numeric_traits<Scalar_T> traits_t;
980  if (val.isnan())
981  return traits_t::NaN();
982 
983  const Scalar_T& s = scalar(val);
984  if (val == s)
985  return traits_t::tan(s);
986 
987  check_complex(val, i, prechecked);
988  return sin(val, i, true) / cos(val, i, true);
989  }
990 
992  template< template<typename, const index_t, const index_t> class Multivector,
993  typename Scalar_T, const index_t LO, const index_t HI >
994  inline
995  const Multivector<Scalar_T,LO,HI>
996  tan(const Multivector<Scalar_T,LO,HI>& val)
997  { return tan(val, complexifier(val), true); }
998 
1000  // Reference: [AS], Section 4.4, p79-83
1001  template< template<typename, const index_t, const index_t> class Multivector,
1002  typename Scalar_T, const index_t LO, const index_t HI >
1003  inline
1004  const Multivector<Scalar_T,LO,HI>
1005  atan(const Multivector<Scalar_T,LO,HI>& val, const Multivector<Scalar_T,LO,HI>& i, bool prechecked)
1006  {
1007  typedef numeric_traits<Scalar_T> traits_t;
1008  if (val.isnan())
1009  return traits_t::NaN();
1010 
1011  const Scalar_T& s = scalar(val);
1012  if (val == s)
1013  return traits_t::atan(s);
1014 
1015  check_complex(val, i, prechecked);
1016  return -i * atanh(i * val, i, true);
1017  }
1018 
1020  // Reference: [AS], Section 4.4, p79-83
1021  template< template<typename, const index_t, const index_t> class Multivector,
1022  typename Scalar_T, const index_t LO, const index_t HI >
1023  inline
1024  const Multivector<Scalar_T,LO,HI>
1025  atan(const Multivector<Scalar_T,LO,HI>& val)
1026  { return atan(val, complexifier(val), true); }
1027 
1028 }
1029 #endif // _GLUCAT_CLIFFORD_ALGEBRA_IMP_H
glucat::vector_part
const std::vector< Scalar_T > vector_part(const Multivector< Scalar_T, LO, HI > &val)
Vector part of multivector, as a vector_t with respect to frame()
Definition: clifford_algebra_imp.h:472
glucat::inv
const Multivector< Scalar_T, LO, HI > inv(const Multivector< Scalar_T, LO, HI > &val)
Geometric multiplicative inverse.
Definition: clifford_algebra_imp.h:350
glucat::operator%
const Multivector< Scalar_T, LO, HI > operator%(const Multivector< Scalar_T, LO, HI > &lhs, const RHS< Scalar_T, LO, HI > &rhs)
Left contraction.
Definition: clifford_algebra_imp.h:272
glucat::asin
const Multivector< Scalar_T, LO, HI > asin(const Multivector< Scalar_T, LO, HI > &val, const Multivector< Scalar_T, LO, HI > &i, const bool prechecked=false)
Inverse sine of multivector with specified complexifier.
Definition: clifford_algebra_imp.h:934
glucat::operator+
const Multivector< Scalar_T, LO, HI > operator+(const Multivector< Scalar_T, LO, HI > &lhs, const Scalar_T &scr)
Geometric sum of multivector and scalar.
Definition: clifford_algebra_imp.h:131
clifford_algebra.h
glucat::scalar
Scalar_T scalar(const Multivector< Scalar_T, LO, HI > &val)
Scalar part.
Definition: clifford_algebra_imp.h:421
glucat::atan
const Multivector< Scalar_T, LO, HI > atan(const Multivector< Scalar_T, LO, HI > &val, const Multivector< Scalar_T, LO, HI > &i, const bool prechecked=false)
Inverse tangent of multivector with specified complexifier.
Definition: clifford_algebra_imp.h:1034
glucat::operator|
const Multivector< Scalar_T, LO, HI > operator|(const Multivector< Scalar_T, LO, HI > &lhs, const RHS< Scalar_T, LO, HI > &rhs)
Transformation via twisted adjoint action.
Definition: clifford_algebra_imp.h:339
glucat::complexifier
const Multivector< Scalar_T, LO, HI > complexifier(const Multivector< Scalar_T, LO, HI > &val)
Square root of -1 which commutes with all members of the frame of the given multivector.
Definition: clifford_algebra_imp.h:535
PyClical.i
i
Definition: PyClical.pyx:1541
glucat::involute
const Multivector< Scalar_T, LO, HI > involute(const Multivector< Scalar_T, LO, HI > &val)
Main involution, each {i} is replaced by -{i} in each term, eg. {1}*{2} -> (-{2})*(-{1})
Definition: clifford_algebra_imp.h:480
glucat::tan
const Multivector< Scalar_T, LO, HI > tan(const Multivector< Scalar_T, LO, HI > &val, const Multivector< Scalar_T, LO, HI > &i, const bool prechecked=false)
Tangent of multivector with specified complexifier.
Definition: clifford_algebra_imp.h:1006
glucat::index_t
int index_t
Size of index_t should be enough to represent LO, HI.
Definition: global.h:106
glucat::real
Scalar_T real(const Multivector< Scalar_T, LO, HI > &val)
Real part: synonym for scalar part.
Definition: clifford_algebra_imp.h:429
glucat::acos
const Multivector< Scalar_T, LO, HI > acos(const Multivector< Scalar_T, LO, HI > &val, const Multivector< Scalar_T, LO, HI > &i, const bool prechecked=false)
Inverse cosine of multivector with specified complexifier.
Definition: clifford_algebra_imp.h:827
glucat::operator!=
bool operator!=(const Multivector< Scalar_T, LO, HI > &lhs, const RHS< Scalar_T, LO, HI > &rhs)
Test for inequality of multivectors.
Definition: clifford_algebra_imp.h:107
glucat::asinh
const Multivector< Scalar_T, LO, HI > asinh(const Multivector< Scalar_T, LO, HI > &val, const Multivector< Scalar_T, LO, HI > &i, const bool prechecked=false)
Inverse hyperbolic sine of multivector with specified complexifier.
Definition: clifford_algebra_imp.h:874
glucat::operator-
const Multivector< Scalar_T, LO, HI > operator-(const Multivector< Scalar_T, LO, HI > &lhs, const Scalar_T &scr)
Geometric difference of multivector and scalar.
Definition: clifford_algebra_imp.h:167
glucat::even
const Multivector< Scalar_T, LO, HI > even(const Multivector< Scalar_T, LO, HI > &val)
Even part.
Definition: clifford_algebra_imp.h:456
glucat::max_abs
Scalar_T max_abs(const Multivector< Scalar_T, LO, HI > &val)
Maximum of absolute values of components of multivector: multivector infinity norm.
Definition: clifford_algebra_imp.h:528
glucat::pure
const Multivector< Scalar_T, LO, HI > pure(const Multivector< Scalar_T, LO, HI > &val)
Pure part.
Definition: clifford_algebra_imp.h:448
glucat::cosh
const Multivector< Scalar_T, LO, HI > cosh(const Multivector< Scalar_T, LO, HI > &val)
Hyperbolic cosine of multivector.
Definition: clifford_algebra_imp.h:749
glucat::pos_mod
LHS_T pos_mod(LHS_T lhs, RHS_T rhs)
Modulo function which works reliably for lhs < 0.
Definition: global.h:216
glucat::star
Scalar_T star(const Multivector< Scalar_T, LO, HI > &lhs, const RHS< Scalar_T, LO, HI > &rhs)
Hestenes scalar product.
Definition: clifford_algebra_imp.h:287
glucat::acosh
const Multivector< Scalar_T, LO, HI > acosh(const Multivector< Scalar_T, LO, HI > &val, const Multivector< Scalar_T, LO, HI > &i, const bool prechecked=false)
Inverse hyperbolic cosine of multivector with specified complexifier.
Definition: clifford_algebra_imp.h:767
glucat::operator/
const Multivector< Scalar_T, LO, HI > operator/(const Multivector< Scalar_T, LO, HI > &lhs, const Scalar_T &scr)
Quotient of multivector and scalar.
Definition: clifford_algebra_imp.h:298
glucat::sinh
const Multivector< Scalar_T, LO, HI > sinh(const Multivector< Scalar_T, LO, HI > &val)
Hyperbolic sine of multivector.
Definition: clifford_algebra_imp.h:855
glucat::abs
Scalar_T abs(const Multivector< Scalar_T, LO, HI > &val)
Absolute value == sqrt(norm)
Definition: clifford_algebra_imp.h:520
glucat::sqrt
const Multivector< Scalar_T, LO, HI > sqrt(const Multivector< Scalar_T, LO, HI > &val, const Multivector< Scalar_T, LO, HI > &i, const bool prechecked=false)
Square root of multivector with specified complexifier.
Definition: clifford_algebra_imp.h:618
scalar.h
PyClical.pi
float pi
Definition: PyClical.pyx:1857
glucat::norm
Scalar_T norm(const Multivector< Scalar_T, LO, HI > &val)
Scalar_T norm == sum of norm of coordinates.
Definition: clifford_algebra_imp.h:512
glucat::log
const Multivector< Scalar_T, LO, HI > log(const Multivector< Scalar_T, LO, HI > &val, const Multivector< Scalar_T, LO, HI > &i, const bool prechecked=false)
Natural logarithm of multivector with specified complexifier.
Definition: clifford_algebra_imp.h:733
glucat::operator*
const Multivector< Scalar_T, LO, HI > operator*(const Multivector< Scalar_T, LO, HI > &lhs, const Scalar_T &scr)
Product of multivector and scalar.
Definition: clifford_algebra_imp.h:201
glucat::quad
Scalar_T quad(const Multivector< Scalar_T, LO, HI > &val)
Scalar_T quadratic form == (rev(x)*x)(0)
Definition: clifford_algebra_imp.h:504
glucat::odd
const Multivector< Scalar_T, LO, HI > odd(const Multivector< Scalar_T, LO, HI > &val)
Odd part.
Definition: clifford_algebra_imp.h:464
glucat::operator&
const Multivector< Scalar_T, LO, HI > operator&(const Multivector< Scalar_T, LO, HI > &lhs, const RHS< Scalar_T, LO, HI > &rhs)
Inner product.
Definition: clifford_algebra_imp.h:257
glucat::numeric_traits
Extra traits which extend numeric limits.
Definition: scalar.h:76
glucat::conj
const Multivector< Scalar_T, LO, HI > conj(const Multivector< Scalar_T, LO, HI > &val)
Conjugation, rev o invo == invo o rev.
Definition: clifford_algebra_imp.h:496
glucat::clifford_exp
const Multivector< Scalar_T, LO, HI > clifford_exp(const Multivector< Scalar_T, LO, HI > &val)
Exponential of multivector.
Definition: clifford_algebra_imp.h:633
glucat
Definition: clifford_algebra.h:39
glucat::check_complex
static void check_complex(const Multivector< Scalar_T, LO, HI > &val, const Multivector< Scalar_T, LO, HI > &i, const bool prechecked=false)
Check that i is a valid complexifier for val.
Definition: clifford_algebra_imp.h:595
glucat::pow
const Multivector< Scalar_T, LO, HI > pow(const Multivector< Scalar_T, LO, HI > &lhs, int rhs)
Integer power of multivector.
Definition: clifford_algebra_imp.h:357
glucat::sin
const Multivector< Scalar_T, LO, HI > sin(const Multivector< Scalar_T, LO, HI > &val, const Multivector< Scalar_T, LO, HI > &i, const bool prechecked=false)
Sine of multivector with specified complexifier.
Definition: clifford_algebra_imp.h:901
glucat::atanh
const Multivector< Scalar_T, LO, HI > atanh(const Multivector< Scalar_T, LO, HI > &val, const Multivector< Scalar_T, LO, HI > &i, const bool prechecked=false)
Inverse hyperbolic tangent of multivector with specified complexifier.
Definition: clifford_algebra_imp.h:981
glucat::clifford_algebra::classname
static const std::string classname()
Definition: clifford_algebra_imp.h:95
glucat::reverse
const Multivector< Scalar_T, LO, HI > reverse(const Multivector< Scalar_T, LO, HI > &val)
Reversion, eg. {1}*{2} -> {2}*{1}.
Definition: clifford_algebra_imp.h:488
glucat::numeric_traits::sqrt
static Scalar_T sqrt(const Scalar_T &val)
Square root of scalar.
Definition: scalar.h:267
glucat::cos
const Multivector< Scalar_T, LO, HI > cos(const Multivector< Scalar_T, LO, HI > &val, const Multivector< Scalar_T, LO, HI > &i, const bool prechecked=false)
Cosine of multivector with specified complexifier.
Definition: clifford_algebra_imp.h:794
glucat::exp
const framed_multi< Scalar_T, LO, HI > exp(const framed_multi< Scalar_T, LO, HI > &val)
Exponential of multivector.
Definition: framed_multi_imp.h:1977
glucat::log2
Scalar_T log2(const Scalar_T &x)
Log base 2 of scalar.
Definition: scalar.h:331
glucat::imag
Scalar_T imag(const Multivector< Scalar_T, LO, HI > &val)
Imaginary part: deprecated (always 0)
Definition: clifford_algebra_imp.h:440
glucat::tanh
const Multivector< Scalar_T, LO, HI > tanh(const Multivector< Scalar_T, LO, HI > &val)
Hyperbolic tangent of multivector.
Definition: clifford_algebra_imp.h:962
glucat::operator^
const Multivector< Scalar_T, LO, HI > operator^(const Multivector< Scalar_T, LO, HI > &lhs, const RHS< Scalar_T, LO, HI > &rhs)
Outer product.
Definition: clifford_algebra_imp.h:242
glucat::outer_pow
const Multivector< Scalar_T, LO, HI > outer_pow(const Multivector< Scalar_T, LO, HI > &lhs, int rhs)
Outer product power of multivector.
Definition: clifford_algebra_imp.h:413
glucat::elliptic
const Multivector< Scalar_T, LO, HI > elliptic(const Multivector< Scalar_T, LO, HI > &val)
Definition: clifford_algebra_imp.h:586