QPMS
Electromagnetic multiple scattering library and toolkit.
vectors.h
Go to the documentation of this file.
1 
4 #ifndef VECTORS_H
5 #define VECTORS_H
6 #include <math.h>
7 #ifndef M_PI_2
8 #define M_PI_2 (1.570796326794896619231321691639751442098584699687552910487)
9 #endif
10 #include "qpms_types.h"
11 #include "qpms_error.h"
12 
13 //static inline double vectors_h_sq(double x) {return x*x;}
14 
15 static const cart2_t CART2_ZERO = {0, 0};
16 static const cart3_t CART3_ZERO = {0, 0, 0};
17 
19 static inline cart2_t cart2_add(const cart2_t a, const cart2_t b) {
20  cart2_t res = {a.x+b.x, a.y+b.y};
21  return res;
22 }
23 
25 static inline cart2_t cart2_substract(const cart2_t a, const cart2_t b) {
26  cart2_t res = {a.x-b.x, a.y-b.y};
27  return res;
28 }
29 
31 static inline cart2_t cart2_scale(const double c, const cart2_t v) {
32  cart2_t res = {c * v.x, c * v.y};
33  return res;
34 }
35 
37 static inline double cart2_dot(const cart2_t a, const cart2_t b) {
38  return a.x * b.x + a.y * b.y;
39 }
40 
41 static inline double cart2_normsq(const cart2_t a) {
42  return cart2_dot(a, a);
43 }
44 
46 static inline double cart2norm(const cart2_t v) {
47  return hypot(v.x, v.y); //sqrt(v.x*v.x + v.y*v.y);
48 }
49 
51 static inline pol_t cart2pol(const cart2_t cart) {
52  pol_t pol;
53  pol.r = cart2norm(cart);
54  pol.phi = atan2(cart.y, cart.x);
55  return pol;
56 }
57 
59 static inline sph_t pol2sph_equator(const pol_t pol) {
60  sph_t sph;
61  sph.r = pol.r;
62  sph.phi = pol.phi;
63  sph.theta = M_PI_2;
64  return sph;
65 }
66 
68 static inline sph_t cart22sph(const cart2_t cart) {
69  sph_t sph;
70  sph.r = cart2norm(cart);
71  sph.theta = M_PI_2;
72  sph.phi = atan2(cart.y, cart.x);
73  return sph;
74 }
75 
77 static inline sph_t cart12sph_zaxis(double z) {
78  sph_t sph = {fabs(z), z < 0 ? M_PI : 0, 0};
79  return sph;
80 }
81 
83 static inline cart3_t cart12cart3z(double z) {
84  cart3_t c = {0, 0, z};
85  return c;
86 }
87 
89 static inline cart3_t cart22cart3xy(const cart2_t a) {
90  cart3_t c;
91  c.x = a.x;
92  c.y = a.y;
93  c.z = 0;
94  return c;
95 }
96 
97 static inline cart2_t cart3xy2cart2(const cart3_t a) {
98  cart2_t c = {a.x, a.y};
99  return c;
100 }
101 
103 static inline double cart3_dot(const cart3_t a, const cart3_t b) {
104  return a.x * b.x + a.y * b.y + a.z * b.z;
105 }
106 
107 
109 static inline cart3_t cart3_vectorprod(const cart3_t a, const cart3_t b) {
110  cart3_t c = {
111  .x = a.y * b.z - a.z * b.y,
112  .y = a.z * b.x - a.x * b.z,
113  .z = a.x * b.y - a.y * b.x,
114  };
115  return c;
116 }
117 
119 static inline double cart3_tripleprod(const cart3_t a, const cart3_t b, const cart3_t c) {
120  return cart3_dot(a, cart3_vectorprod(b, c));
121 }
122 
124 static inline double cart3_normsq(const cart3_t a) {
125  return cart3_dot(a, a);
126 }
127 
129 static inline double cart3norm(const cart3_t v) {
130  return sqrt(cart3_normsq(v));
131 }
132 
134 static inline sph_t cart2sph(const cart3_t cart) {
135  sph_t sph;
136  sph.r = cart3norm(cart);
137  sph.theta = sph.r ? acos(cart.z / sph.r) : M_PI_2;
138  sph.phi = atan2(cart.y, cart.x);
139  return sph;
140 }
141 
143 static inline cart3_t sph2cart(const sph_t sph) {
144  cart3_t cart;
145  double sin_th =
146 #ifdef QPMS_VECTORS_NICE_TRANSFORMATIONS
147  (sph.theta == M_PI) ? 0 :
148 #endif
149  sin(sph.theta);
150  cart.x = sph.r * sin_th * cos(sph.phi);
151  cart.y = sph.r * sin_th * sin(sph.phi);
152  cart.z = sph.r * cos(sph.theta);
153  return cart;
154 }
155 
157 static inline cart2_t pol2cart(const pol_t pol) {
158  cart2_t cart;
159  cart.x = pol.r * cos(pol.phi);
160  cart.y = pol.r * sin(pol.phi);
161  return cart;
162 }
163 
165 static inline cart3_t pol2cart3_equator(const pol_t pol) {
166  cart2_t c = pol2cart(pol);
167  cart3_t cart3 = {c.x, c.y, 0};
168  return cart3;
169 }
170 
171 
173 static inline cart3_t cart3_add(const cart3_t a, const cart3_t b) {
174  cart3_t res = {a.x+b.x, a.y+b.y, a.z+b.z};
175  return res;
176 }
177 
179 static inline cart3_t cart3_substract(const cart3_t a, const cart3_t b) {
180  cart3_t res = {a.x-b.x, a.y-b.y, a.z-b.z};
181  return res;
182 }
183 
185 static inline cart3_t cart3_scale(const double c, const cart3_t v) {
186  cart3_t res = {c * v.x, c * v.y, c * v.z};
187  return res;
188 }
189 
191 static inline cart3_t cart3_divscale( const cart3_t v, const double c) {
192  cart3_t res = {v.x / c, v.y / c, v.z / c};
193  return res;
194 }
195 
197 static inline double cart3_dist(const cart3_t a, const cart3_t b) {
198  return cart3norm(cart3_substract(a,b));
199 }
200 
201 static inline bool cart3_isclose(const cart3_t a, const cart3_t b, double rtol, double atol) {
202  return cart3_dist(a,b) <= atol + rtol * (cart3norm(b) + cart3norm(a)) * .5;
203 }
204 
206 static inline ccart3_t ccart3_scale(const complex double c, const ccart3_t v) {
207  ccart3_t res = {c * v.x, c * v.y, c * v.z};
208  return res;
209 }
210 
212 static inline ccart3_t ccart3_add(const ccart3_t a, const ccart3_t b) {
213  ccart3_t res = {a.x+b.x, a.y+b.y, a.z+b.z};
214  return res;
215 }
216 
218 static inline ccart3_t ccart3_substract(const ccart3_t a, const ccart3_t b) {
219  ccart3_t res = {a.x-b.x, a.y-b.y, a.z-b.z};
220  return res;
221 }
222 
224 static inline complex double ccart3_dotnc(const ccart3_t a, const ccart3_t b) {
225  return a.x * b.x + a.y * b.y + a.z * b.z;
226 }
227 
229 static inline ccart3_t cart32ccart3(cart3_t c){
230  ccart3_t res = {c.x, c.y, c.z};
231  return res;
232 }
233 
235 static inline csphvec_t csphvec_add(const csphvec_t a, const csphvec_t b) {
236  csphvec_t res = {a.rc + b.rc, a.thetac + b.thetac, a.phic + b.phic};
237  return res;
238 }
239 
241 static inline csphvec_t csphvec_substract(const csphvec_t a, const csphvec_t b) {
242  csphvec_t res = {a.rc - b.rc, a.thetac - b.thetac, a.phic - b.phic};
243  return res;
244 }
245 
247 static inline csphvec_t csphvec_scale(complex double c, const csphvec_t v) {
248  csphvec_t res = {c * v.rc, c * v.thetac, c * v.phic};
249  return res;
250 }
251 
253 static inline complex double csphvec_dotnc(const csphvec_t a, const csphvec_t b) {
254  //N.B. no complex conjugation done here
255  return a.rc * b.rc + a.thetac * b.thetac + a.phic * b.phic;
256 }
257 
259 static inline sph_t sph_scale(double c, const sph_t s) {
260  sph_t res = {c * s.r, s.theta, s.phi};
261  return res;
262 }
263 
265 static inline csph_t sph_cscale(complex double c, const sph_t s) {
266  csph_t res = {c * s.r, s.theta, s.phi};
267  return res;
268 }
269 
271 // equivalent to sph_loccart2cart in qpms_p.py
272 static inline ccart3_t csphvec2ccart(const csphvec_t sphvec, const sph_t at) {
273  const double st = sin(at.theta);
274  const double ct = cos(at.theta);
275  const double sf = sin(at.phi);
276  const double cf = cos(at.phi);
277  const double rx = st * cf;
278  const double ry = st * sf;
279  const double rz = ct;
280  const double tx = ct * cf;
281  const double ty = ct * sf;
282  const double tz = -st;
283  const double fx = -sf;
284  const double fy = cf;
285  const double fz = 0.;
286  ccart3_t res;
287  res.x = rx * sphvec.rc + tx * sphvec.thetac + fx * sphvec.phic;
288  res.y = ry * sphvec.rc + ty * sphvec.thetac + fy * sphvec.phic;
289  res.z = rz * sphvec.rc + tz * sphvec.thetac + fz * sphvec.phic;
290  return res;
291 }
292 
294 
300 static inline ccart3_t csphvec2ccart_csph(const csphvec_t sphvec, const csph_t at) {
301  const sph_t atreal = {0 /*not used*/, at.theta, at.phi};
302  return csphvec2ccart(sphvec, atreal);
303 }
304 
306 static inline csphvec_t ccart2csphvec(const ccart3_t cartvec, const sph_t at) {
307  // this chunk is copy-pasted from csphvec2cart, so there should be a better way...
308  const double st = sin(at.theta);
309  const double ct = cos(at.theta);
310  const double sf = sin(at.phi);
311  const double cf = cos(at.phi);
312  const double rx = st * cf;
313  const double ry = st * sf;
314  const double rz = ct;
315  const double tx = ct * cf;
316  const double ty = ct * sf;
317  const double tz = -st;
318  const double fx = -sf;
319  const double fy = cf;
320  const double fz = 0.;
321  csphvec_t res;
322  res.rc = rx * cartvec.x + ry * cartvec.y + rz * cartvec.z;
323  res.thetac = tx * cartvec.x + ty * cartvec.y + tz * cartvec.z;
324  res.phic = fx * cartvec.x + fy * cartvec.y + fz * cartvec.z;
325  return res;
326 }
327 
329 static inline csph_t sph2csph(sph_t s) {
330  csph_t cs = {s.r, s.theta, s.phi};
331  return cs;
332 }
333 
335 static inline sph_t csph2sph(csph_t s) {
336  sph_t rs = {creal(s.r), s.theta, s.phi};
337  return rs;
338 }
339 
341 
350 static inline csph_t ccart2csph(const ccart3_t cart) {
351  cart3_t rcart = {creal(cart.x), creal(cart.y), creal(cart.z)};
352  cart3_t icart = {cimag(cart.x), cimag(cart.y), cimag(cart.z)};
353  csph_t sph = sph2csph(cart2sph(rcart));
354  sph.r += I * cart3_dot(icart,rcart) / cart3norm(rcart);
355  return sph;
356 }
357 
359 static inline csph_t cart2csph(const cart3_t cart) {
360  csph_t sph;
361  sph.r = cart3norm(cart);
362  sph.theta = sph.r ? acos(cart.z / sph.r) : M_PI_2;
363  sph.phi = atan2(cart.y, cart.x);
364  return sph;
365 }
366 
368 static inline ccart3_t csph2ccart(const csph_t sph) {
369  ccart3_t cart;
370  double sin_th =
371 #ifdef QPMS_VECTORS_NICE_TRANSFORMATIONS
372  (sph.theta == M_PI) ? 0 :
373 #endif
374  sin(sph.theta);
375  cart.x = sph.r * sin_th * cos(sph.phi);
376  cart.y = sph.r * sin_th * sin(sph.phi);
377  cart.z = sph.r * cos(sph.theta);
378  return cart;
379 }
380 
381 
382 void print_csphvec(csphvec_t);
383 void print_ccart3(ccart3_t);
384 void print_cart3(cart3_t);
385 void print_sph(sph_t);
386 
387 // kahan sums for various types... TODO make generic code using macros
388 
390 static inline void ccart3_kahaninit(ccart3_t *sum, ccart3_t *compensation) {
391  sum->x = sum->y = sum->z = compensation->x = compensation->y = compensation->z = 0;
392 }
394 static inline void csphvec_kahaninit(csphvec_t *sum, csphvec_t *compensation) {
395  sum->rc = sum->thetac = sum->phic = compensation->rc = compensation->thetac = compensation->phic = 0;
396 }
397 
399 static inline void ccart3_kahanadd(ccart3_t *sum, ccart3_t *compensation, const ccart3_t input) {
400  ccart3_t comped_input = ccart3_substract(input, *compensation);
401  ccart3_t nsum = ccart3_add(*sum, comped_input);
402  *compensation = ccart3_substract(ccart3_substract(nsum, *sum), comped_input);
403  *sum = nsum;
404 }
405 
407 static inline void csphvec_kahanadd(csphvec_t *sum, csphvec_t *compensation, const csphvec_t input) {
408  csphvec_t comped_input = csphvec_substract(input, *compensation);
409  csphvec_t nsum = csphvec_add(*sum, comped_input);
410  *compensation = csphvec_substract(csphvec_substract(nsum, *sum), comped_input);
411  *sum = nsum;
412 }
413 
415 static inline double csphvec_norm(const csphvec_t a) {
416  return sqrt(creal(a.rc * conj(a.rc) + a.thetac * conj(a.thetac) + a.phic * conj(a.phic)));
417 }
418 
419 static inline double csphvec_reldiff_abstol(const csphvec_t a, const csphvec_t b, double tolerance) {
420  double anorm = csphvec_norm(a);
421  double bnorm = csphvec_norm(b);
422  if (anorm <= tolerance && bnorm <= tolerance) return 0;
423  return csphvec_norm(csphvec_substract(a,b)) / (anorm + bnorm);
424 }
425 
426 static inline double csphvec_reldiff(const csphvec_t a, const csphvec_t b) {
427  return csphvec_reldiff_abstol(a, b, 0);
428 }
429 
430 
457 
460  switch(t & QPMS_COORDS_BITRANGE) {
461  case QPMS_COORDS_SPH:
462  return p.sph;
463  break;
464  case QPMS_COORDS_POL:
465  return pol2sph_equator(p.pol);
466  break;
467  case QPMS_COORDS_CART3:
468  return cart2sph(p.cart3);
469  break;
470  case QPMS_COORDS_CART2:
471  return cart22sph(p.cart2);
472  break;
473  case QPMS_COORDS_CART1:
474  return cart12sph_zaxis(p.z);
475  break;
476  }
477  QPMS_WTF;
478 }
479 
480 
482 
485  switch(t & QPMS_COORDS_BITRANGE) {
486  case QPMS_COORDS_SPH:
487  return sph2cart(p.sph);
488  break;
489  case QPMS_COORDS_POL:
490  return pol2cart3_equator(p.pol);
491  break;
492  case QPMS_COORDS_CART3:
493  return p.cart3;
494  break;
495  case QPMS_COORDS_CART2:
496  return cart22cart3xy(p.cart2);
497  break;
498  case QPMS_COORDS_CART1:
499  return cart12cart3z(p.z);
500  break;
501  }
502  QPMS_WTF;
503 }
504 
506 // The implementation is simple and stupid, do not use for heavy computations.
508  return cart3norm(anycoord2cart3(p, t));
509 }
510 
511 #if 0
512 // Convenience identifiers for return values.
513 static const cart3_t CART3_INVALID = {NAN, NAN, NAN};
514 static const cart2_t CART2_INVALID = {NAN, NAN};
515 static const double CART1_INVALID = NAN;
516 static const sph_t SPH_INVALID = {NAN, NAN, NAN};
517 static const pol_t POL_INVALID = {NAN, NAN};
518 #endif
519 
521 
524  switch(t & QPMS_COORDS_BITRANGE) {
525  case QPMS_COORDS_SPH:
526  case QPMS_COORDS_CART3:
527  QPMS_PR_ERROR("Implicit conversion from 3D to 2D"
528  " coordinates not allowed");
529  break;
530  case QPMS_COORDS_POL:
531  return p.pol;
532  break;
533  case QPMS_COORDS_CART2:
534  return cart2pol(p.cart2);
535  break;
536  case QPMS_COORDS_CART1:
537  QPMS_PR_ERROR("Implicit conversion from 1D to 2D"
538  " coordinates not allowed");
539  break;
540  }
541  QPMS_WTF;
542 }
543 
544 
546 
549  switch(t & QPMS_COORDS_BITRANGE) {
550  case QPMS_COORDS_SPH:
551  case QPMS_COORDS_CART3:
552  QPMS_PR_ERROR("Implicit conversion from 3D to 2D"
553  " coordinates not allowed");
554  break;
555  case QPMS_COORDS_POL:
556  return pol2cart(p.pol);
557  break;
558  case QPMS_COORDS_CART2:
559  return p.cart2;
560  break;
561  case QPMS_COORDS_CART1:
562  QPMS_PR_ERROR("Implicit conversion from 1D to 2D"
563  " coordinates not allowed");
564  break;
565  }
566  QPMS_WTF;
567 }
568 
569 
571 
575  return p.z;
576  else
577  QPMS_PR_ERROR("Implicit conversion from nD (n > 1)"
578  " to 1D not allowed.");
579 }
580 
581 
583 
584 static inline void qpms_array_coord_transform(void *dest, qpms_coord_system_t tdest,
585  const void *src, qpms_coord_system_t tsrc, size_t nmemb) {
586  switch(tdest & QPMS_COORDS_BITRANGE) {
587  case QPMS_COORDS_SPH:
588  {
589  sph_t *d = (sph_t *) dest;
590  switch (tsrc & QPMS_COORDS_BITRANGE) {
591  case QPMS_COORDS_SPH: {
592  const sph_t *s = src;
593  for(size_t i = 0; i < nmemb; ++i)
594  d[i] = s[i];
595  return;
596  } break;
597  case QPMS_COORDS_CART3: {
598  const cart3_t *s = src;
599  for(size_t i = 0; i < nmemb; ++i)
600  d[i] = cart2sph(s[i]);
601  return;
602  } break;
603  case QPMS_COORDS_POL: {
604  const pol_t *s = src;
605  for(size_t i = 0; i < nmemb; ++i)
606  d[i] = pol2sph_equator(s[i]);
607  return;
608  } break;
609  case QPMS_COORDS_CART2: {
610  const cart2_t *s = src;
611  for(size_t i = 0; i < nmemb; ++i)
612  d[i] = cart22sph(s[i]);
613  return;
614  } break;
615  case QPMS_COORDS_CART1: {
616  const double *s = src;
617  for(size_t i = 0; i < nmemb; ++i)
618  d[i] = cart12sph_zaxis(s[i]);
619  return;
620  } break;
621  }
622  QPMS_WTF;
623  }
624  break;
625  case QPMS_COORDS_CART3:
626  {
627  cart3_t *d = (cart3_t *) dest;
628  switch (tsrc & QPMS_COORDS_BITRANGE) {
629  case QPMS_COORDS_SPH: {
630  const sph_t *s = src;
631  for(size_t i = 0; i < nmemb; ++i)
632  d[i] = sph2cart(s[i]);
633  return;
634  } break;
635  case QPMS_COORDS_CART3: {
636  const cart3_t *s = src;
637  for(size_t i = 0; i < nmemb; ++i)
638  d[i] = s[i];
639  return;
640  } break;
641  case QPMS_COORDS_POL: {
642  const pol_t *s = src;
643  for(size_t i = 0; i < nmemb; ++i)
644  d[i] = pol2cart3_equator(s[i]);
645  return;
646  } break;
647  case QPMS_COORDS_CART2: {
648  const cart2_t *s = src;
649  for(size_t i = 0; i < nmemb; ++i)
650  d[i] = cart22cart3xy(s[i]);
651  return;
652  } break;
653  case QPMS_COORDS_CART1: {
654  const double *s = src;
655  for(size_t i = 0; i < nmemb; ++i)
656  d[i] = cart12cart3z(s[i]);
657  return;
658  } break;
659  }
660  QPMS_WTF;
661  }
662  break;
663  case QPMS_COORDS_POL:
664  {
665  pol_t *d = (pol_t *) dest;
666  switch (tsrc & QPMS_COORDS_BITRANGE) {
667  case QPMS_COORDS_SPH:
668  case QPMS_COORDS_CART3:
669  QPMS_PR_ERROR("Implicit conversion from 3D to 2D coordinates not allowed");
670  break;
671  case QPMS_COORDS_POL: {
672  const pol_t *s = src;
673  for(size_t i = 0; i < nmemb; ++i)
674  d[i] = s[i];
675  return;
676  } break;
677  case QPMS_COORDS_CART2: {
678  const cart2_t *s = src;
679  for(size_t i = 0; i < nmemb; ++i)
680  d[i] = cart2pol(s[i]);
681  return;
682  } break;
683  case QPMS_COORDS_CART1:
684  QPMS_PR_ERROR("Implicit conversion from 3D to 1D coordinates not allowed");
685  break;
686  }
687  QPMS_WTF;
688  }
689  break;
690  case QPMS_COORDS_CART2:
691  {
692  cart2_t *d = (cart2_t *) dest;
693  switch (tsrc & QPMS_COORDS_BITRANGE) {
694  case QPMS_COORDS_SPH:
695  case QPMS_COORDS_CART3:
696  QPMS_PR_ERROR("Implicit conversion from 3D to 2D coordinates not allowed");
697  break;
698  case QPMS_COORDS_POL: {
699  const pol_t *s = src;
700  for(size_t i = 0; i < nmemb; ++i)
701  d[i] = pol2cart(s[i]);
702  return;
703  } break;
704  case QPMS_COORDS_CART2: {
705  const cart2_t *s = src;
706  for(size_t i = 0; i < nmemb; ++i)
707  d[i] = s[i];
708  return;
709  } break;
710  case QPMS_COORDS_CART1:
711  QPMS_PR_ERROR("Implicit conversion from 3D to 1D coordinates not allowed");
712  break;
713  }
714  QPMS_WTF;
715  }
716  break;
717  case QPMS_COORDS_CART1:
718  {
719  double *d = (double *) dest;
720  switch (tsrc & QPMS_COORDS_BITRANGE) {
721  case QPMS_COORDS_SPH:
722  case QPMS_COORDS_CART3:
723  QPMS_PR_ERROR("Implicit conversion from 3D to 2D coordinates not allowed");
724  break;
725  case QPMS_COORDS_POL:
726  case QPMS_COORDS_CART2:
727  QPMS_PR_ERROR("Implicit conversion from 3D to 1D coordinates not allowed");
728  break;
729  case QPMS_COORDS_CART1: {
730  const double *s = src;
731  for(size_t i = 0; i < nmemb; ++i)
732  d[i] = s[i];
733  return;
734  } break;
735  }
736  QPMS_WTF;
737  }
738  break;
739  }
740  QPMS_WTF;
741 }
742 
743 
745 
746 static inline void anycoord_arr2something(void *dest, qpms_coord_system_t tdest,
747  const anycoord_point_t *src, qpms_coord_system_t tsrc, size_t nmemb) {
748  if(nmemb) {
749  switch(tdest & QPMS_COORDS_BITRANGE) {
750  case QPMS_COORDS_SPH:
751  {
752  sph_t *d = (sph_t *) dest;
753  switch (tsrc & QPMS_COORDS_BITRANGE) {
754  case QPMS_COORDS_SPH:
755  for(size_t i = 0; i < nmemb; ++i)
756  d[i] = src[i].sph;
757  return; break;
758  case QPMS_COORDS_CART3:
759  for(size_t i = 0; i < nmemb; ++i)
760  d[i] = cart2sph(src[i].cart3);
761  return; break;
762  case QPMS_COORDS_POL:
763  for(size_t i = 0; i < nmemb; ++i)
764  d[i] = pol2sph_equator(src[i].pol);
765  return; break;
766  case QPMS_COORDS_CART2:
767  for(size_t i = 0; i < nmemb; ++i)
768  d[i] = cart22sph(src[i].cart2);
769  return; break;
770  case QPMS_COORDS_CART1:
771  for(size_t i = 0; i < nmemb; ++i)
772  d[i] = cart12sph_zaxis(src[i].z);
773  return; break;
774  }
775  QPMS_WTF;
776  }
777  break;
778  case QPMS_COORDS_CART3:
779  {
780  cart3_t *d = (cart3_t *) dest;
781  switch (tsrc & QPMS_COORDS_BITRANGE) {
782  case QPMS_COORDS_SPH:
783  for(size_t i = 0; i < nmemb; ++i)
784  d[i] = sph2cart(src[i].sph);
785  return; break;
786  case QPMS_COORDS_CART3:
787  for(size_t i = 0; i < nmemb; ++i)
788  d[i] = src[i].cart3;
789  return; break;
790  case QPMS_COORDS_POL:
791  for(size_t i = 0; i < nmemb; ++i)
792  d[i] = pol2cart3_equator(src[i].pol);
793  return; break;
794  case QPMS_COORDS_CART2:
795  for(size_t i = 0; i < nmemb; ++i)
796  d[i] = cart22cart3xy(src[i].cart2);
797  return; break;
798  case QPMS_COORDS_CART1:
799  for(size_t i = 0; i < nmemb; ++i)
800  d[i] = cart12cart3z(src[i].z);
801  return; break;
802  }
803  QPMS_WTF;
804  }
805  break;
806  case QPMS_COORDS_POL:
807  {
808  pol_t *d = (pol_t *) dest;
809  switch (tsrc & QPMS_COORDS_BITRANGE) {
810  case QPMS_COORDS_SPH:
811  case QPMS_COORDS_CART3:
812  QPMS_PR_ERROR("Implicit conversion from 3D to 2D coordinates not allowed");
813  break;
814  case QPMS_COORDS_POL:
815  for(size_t i = 0; i < nmemb; ++i)
816  d[i] = src[i].pol;
817  return; break;
818  case QPMS_COORDS_CART2:
819  for(size_t i = 0; i < nmemb; ++i)
820  d[i] = cart2pol(src[i].cart2);
821  return; break;
822  case QPMS_COORDS_CART1:
823  QPMS_PR_ERROR("Implicit conversion from 3D to 1D coordinates not allowed");
824  break;
825  }
826  QPMS_WTF;
827  }
828  break;
829  case QPMS_COORDS_CART2:
830  {
831  cart2_t *d = (cart2_t *) dest;
832  switch (tsrc & QPMS_COORDS_BITRANGE) {
833  case QPMS_COORDS_SPH:
834  case QPMS_COORDS_CART3:
835  QPMS_PR_ERROR("Implicit conversion from 3D to 2D coordinates not allowed");
836  break;
837  case QPMS_COORDS_POL:
838  for(size_t i = 0; i < nmemb; ++i)
839  d[i] = pol2cart(src[i].pol);
840  return; break;
841  case QPMS_COORDS_CART2:
842  for(size_t i = 0; i < nmemb; ++i)
843  d[i] = src[i].cart2;
844  return; break;
845  case QPMS_COORDS_CART1:
846  QPMS_PR_ERROR("Implicit conversion from 3D to 1D coordinates not allowed");
847  break;
848  }
849  QPMS_WTF;
850  }
851  break;
852  case QPMS_COORDS_CART1:
853  {
854  double *d = (double *) dest;
855  switch (tsrc & QPMS_COORDS_BITRANGE) {
856  case QPMS_COORDS_SPH:
857  case QPMS_COORDS_CART3:
858  QPMS_PR_ERROR("Implicit conversion from 3D to 2D coordinates not allowed");
859  break;
860  case QPMS_COORDS_POL:
861  case QPMS_COORDS_CART2:
862  QPMS_PR_ERROR("Implicit conversion from 3D to 1D coordinates not allowed");
863  break;
864  case QPMS_COORDS_CART1:
865  for(size_t i = 0; i < nmemb; ++i)
866  d[i] = src[i].z;
867  return; break;
868  }
869  QPMS_WTF;
870  }
871  break;
872  }
873  QPMS_WTF;
874  }
875 }
876 
878 static inline void cart3_to_double_array(double a[], cart3_t b) {
879  a[0] = b.x; a[1] = b.y; a[2] = b.z;
880 }
881 
883 static inline cart3_t cart3_from_double_array(const double a[]) {
884  cart3_t b = {.x = a[0], .y = a[1], .z = a[1]};
885  return b;
886 }
887 
889 static inline void cart2_to_double_array(double a[], cart2_t b) {
890  a[0] = b.x; a[1] = b.y;
891 }
892 
894 static inline cart2_t cart2_from_double_array(const double a[]) {
895  cart2_t b = {.x = a[0], .y = a[1]};
896  return b;
897 }
898 
899 
900 typedef double matrix3d[3][3];
901 typedef double matrix2d[2][2];
902 typedef complex double cmatrix3d[3][3];
903 typedef complex double cmatrix2d[2][2];
904 #endif //VECTORS_H
QPMS miscellanous internal error handling functions and macros.
#define QPMS_PR_ERROR(msg,...)
Prints a given error message and aborts the program.
Definition: qpms_error.h:197
#define QPMS_WTF
Prints an "unexpected error" message and aborts the program.
Definition: qpms_error.h:181
Common qpms types.
qpms_coord_system_t
Enum codes for common coordinate systems.
Definition: qpms_types.h:238
@ QPMS_COORDS_CART2
2D cartesian.
Definition: qpms_types.h:244
@ QPMS_COORDS_CART3
Definition: qpms_types.h:245
@ QPMS_COORDS_BITRANGE
Convenience bitmask (not a valid flag!).
Definition: qpms_types.h:247
@ QPMS_COORDS_CART1
1D cartesian (= double).
Definition: qpms_types.h:241
@ QPMS_COORDS_SPH
3D spherical.
Definition: qpms_types.h:243
@ QPMS_COORDS_POL
2D polar.
Definition: qpms_types.h:242
2D cartesian coordinates. See also vectors.h.
Definition: qpms_types.h:202
3D cartesian coordinates. See also vectors.h.
Definition: qpms_types.h:186
3D complex (actually 6D) coordinates. See also vectors.h.
Definition: qpms_types.h:191
Spherical coordinates with complex radial component. See also vectors.h.
Definition: qpms_types.h:212
3D complex vector components in local spherical basis. See also vectors.h.
Definition: qpms_types.h:218
2D polar coordinates. See also vectors.h.
Definition: qpms_types.h:223
Spherical coordinates. See also vectors.h.
Definition: qpms_types.h:207
Union type capable to contain various 1D, 2D and 3D coordinates.
Definition: qpms_types.h:229
double z
1D cartesian coordinate.
Definition: qpms_types.h:230
static double cart3_dot(const cart3_t a, const cart3_t b)
3D vector dot product.
Definition: vectors.h:103
static double csphvec_norm(const csphvec_t a)
Euclidian norm of a vector in geographic coordinates.
Definition: vectors.h:415
static cart3_t cart3_add(const cart3_t a, const cart3_t b)
3D vector addition.
Definition: vectors.h:173
static ccart3_t ccart3_substract(const ccart3_t a, const ccart3_t b)
Complex 3D vector substraction.
Definition: vectors.h:218
static csphvec_t csphvec_substract(const csphvec_t a, const csphvec_t b)
Complex 3D vector (geographic coordinates) substraction.
Definition: vectors.h:241
static ccart3_t csph2ccart(const csph_t sph)
Coordinate transform of csph_t to ccart3_t.
Definition: vectors.h:368
static sph_t sph_scale(double c, const sph_t s)
Spherical coordinate system scaling.
Definition: vectors.h:259
static cart2_t cart2_substract(const cart2_t a, const cart2_t b)
2D vector substraction.
Definition: vectors.h:25
static pol_t anycoord2pol(anycoord_point_t p, qpms_coord_system_t t)
Conversion from anycoord_point_t to explicitly polar coordinates.
Definition: vectors.h:523
static cart2_t cart2_from_double_array(const double a[])
Converts array of doubles to cart2_t.
Definition: vectors.h:894
static csph_t sph2csph(sph_t s)
Convert sph_t to csph_t.
Definition: vectors.h:329
static cart3_t cart3_from_double_array(const double a[])
Converts array of doubles to cart3_t.
Definition: vectors.h:883
static pol_t cart2pol(const cart2_t cart)
2D cartesian to polar coordinates conversion. See Coordinate systems and default conversions.
Definition: vectors.h:51
static void qpms_array_coord_transform(void *dest, qpms_coord_system_t tdest, const void *src, qpms_coord_system_t tsrc, size_t nmemb)
Coordinate conversion of point arrays (something to something).
Definition: vectors.h:584
static sph_t cart22sph(const cart2_t cart)
2D cartesian to spherical coordinates conversion. See Coordinate systems and default conversions.
Definition: vectors.h:68
static csph_t cart2csph(const cart3_t cart)
Real 3D cartesian to spherical (complex r) coordinates conversion. See Coordinate systems and default...
Definition: vectors.h:359
static cart3_t cart3_vectorprod(const cart3_t a, const cart3_t b)
3D vector product a.k.a. cross product.
Definition: vectors.h:109
static csphvec_t csphvec_add(const csphvec_t a, const csphvec_t b)
Complex 3D vector (geographic coordinates) addition.
Definition: vectors.h:235
static sph_t cart2sph(const cart3_t cart)
3D cartesian to spherical coordinates conversion. See Coordinate systems and default conversions.
Definition: vectors.h:134
static cart3_t cart22cart3xy(const cart2_t a)
2D to 3D cartesian coordinates conversion. See Coordinate systems and default conversions.
Definition: vectors.h:89
static sph_t csph2sph(csph_t s)
Convert csph_t to sph_t, discarding the imaginary part of radial component.
Definition: vectors.h:335
static double cart2norm(const cart2_t v)
2D vector euclidian norm.
Definition: vectors.h:46
static csphvec_t ccart2csphvec(const ccart3_t cartvec, const sph_t at)
Coordinate transform of a vector in global cartesian to local geographic system.
Definition: vectors.h:306
static cart3_t anycoord2cart3(anycoord_point_t p, qpms_coord_system_t t)
Conversion from anycoord_point_t to explicitly 3D cartesian coordinates.
Definition: vectors.h:484
static void ccart3_kahaninit(ccart3_t *sum, ccart3_t *compensation)
Kanan sum initialisation for ccart3_t.
Definition: vectors.h:390
static cart3_t pol2cart3_equator(const pol_t pol)
Polar to 3D cartesian coordinates conversion. See Coordinate systems and default conversions.
Definition: vectors.h:165
static cart3_t cart3_scale(const double c, const cart3_t v)
3D vector scaling
Definition: vectors.h:185
static ccart3_t csphvec2ccart(const csphvec_t sphvec, const sph_t at)
Coordinate transform of a vector in local geographic to global cartesian system.
Definition: vectors.h:272
static cart3_t cart3_substract(const cart3_t a, const cart3_t b)
3D vector substraction.
Definition: vectors.h:179
static double cart3_tripleprod(const cart3_t a, const cart3_t b, const cart3_t c)
Scalar triple product .
Definition: vectors.h:119
static void anycoord_arr2something(void *dest, qpms_coord_system_t tdest, const anycoord_point_t *src, qpms_coord_system_t tsrc, size_t nmemb)
Coordinate conversion of point arrays (anycoord_point_t to something).
Definition: vectors.h:746
static sph_t pol2sph_equator(const pol_t pol)
Polar to spherical coordinates conversion. See Coordinate systems and default conversions.
Definition: vectors.h:59
static ccart3_t csphvec2ccart_csph(const csphvec_t sphvec, const csph_t at)
Coordinate transform of a vector in local geographic to global cartesian system.
Definition: vectors.h:300
static void csphvec_kahanadd(csphvec_t *sum, csphvec_t *compensation, const csphvec_t input)
Add element to Kahan sum (csphvec_t).
Definition: vectors.h:407
static cart2_t cart2_scale(const double c, const cart2_t v)
2D vector scaling.
Definition: vectors.h:31
static void cart3_to_double_array(double a[], cart3_t b)
Converts cart3_t to array of doubles.
Definition: vectors.h:878
static double cart2_dot(const cart2_t a, const cart2_t b)
2D vector dot product.
Definition: vectors.h:37
static ccart3_t cart32ccart3(cart3_t c)
Convert cart3_t to ccart3_t.
Definition: vectors.h:229
static ccart3_t ccart3_scale(const complex double c, const ccart3_t v)
Complex 3D vector scaling.
Definition: vectors.h:206
static sph_t cart12sph_zaxis(double z)
1D cartesian to spherical coordinates conversion. See Coordinate systems and default conversions.
Definition: vectors.h:77
static double cart3norm(const cart3_t v)
3D vector euclidian norm.
Definition: vectors.h:129
static complex double csphvec_dotnc(const csphvec_t a, const csphvec_t b)
Complex 3D vector (geographic coordinates) "dot product" without conjugation.
Definition: vectors.h:253
static void csphvec_kahaninit(csphvec_t *sum, csphvec_t *compensation)
Kanan sum initialisation for csphvec_t.
Definition: vectors.h:394
static csph_t sph_cscale(complex double c, const sph_t s)
"Complex spherical" coordinate system scaling.
Definition: vectors.h:265
static double cart3_normsq(const cart3_t a)
3D vector euclidian norm squared.
Definition: vectors.h:124
static csph_t ccart2csph(const ccart3_t cart)
Lossy coordinate transform of ccart3_t to csph_t.
Definition: vectors.h:350
static sph_t anycoord2sph(anycoord_point_t p, qpms_coord_system_t t)
Conversion from anycoord_point_t to explicitly spherical coordinates.
Definition: vectors.h:459
static double anycoord_norm(anycoord_point_t p, qpms_coord_system_t t)
Cartesian norm of anycoord_point_t.
Definition: vectors.h:507
static ccart3_t ccart3_add(const ccart3_t a, const ccart3_t b)
Complex 3D vector adition.
Definition: vectors.h:212
static void cart2_to_double_array(double a[], cart2_t b)
Converts cart2_t to array of doubles.
Definition: vectors.h:889
static complex double ccart3_dotnc(const ccart3_t a, const ccart3_t b)
Complex 3D cartesian vector "dot product" without conjugation.
Definition: vectors.h:224
static cart3_t cart12cart3z(double z)
1D to 3D cartesian coordinates conversion. See Coordinate systems and default conversions.
Definition: vectors.h:83
static double cart3_dist(const cart3_t a, const cart3_t b)
Euclidian distance between two 3D points.
Definition: vectors.h:197
static cart3_t sph2cart(const sph_t sph)
Spherical to 3D cartesian coordinates conversion. See Coordinate systems and default conversions.
Definition: vectors.h:143
static void ccart3_kahanadd(ccart3_t *sum, ccart3_t *compensation, const ccart3_t input)
Add element to Kahan sum (ccart3_t).
Definition: vectors.h:399
static double anycoord2cart1(anycoord_point_t p, qpms_coord_system_t t)
Conversion from anycoord_point_t to explicitly 1D cartesian coordinates.
Definition: vectors.h:573
static cart3_t cart3_divscale(const cart3_t v, const double c)
3D vector division by scalar (N.B. argument order).
Definition: vectors.h:191
static cart2_t cart2_add(const cart2_t a, const cart2_t b)
2D vector addition.
Definition: vectors.h:19
static cart2_t pol2cart(const pol_t pol)
Polar to 2D cartesian coordinates conversion. See Coordinate systems and default conversions.
Definition: vectors.h:157
static cart2_t anycoord2cart2(anycoord_point_t p, qpms_coord_system_t t)
Conversion from anycoord_point_t to explicitly 2D cartesian coordinates.
Definition: vectors.h:548
static csphvec_t csphvec_scale(complex double c, const csphvec_t v)
Complex 3D vector (geographic coordinates) scaling.
Definition: vectors.h:247