complex.c 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. #include <u.h>
  2. #include <libc.h>
  3. #include "map.h"
  4. /*complex divide, defensive against overflow from
  5. * * and /, but not from + and -
  6. * assumes underflow yields 0.0
  7. * uses identities:
  8. * (a + bi)/(c + di) = ((a + bd/c) + (b - ad/c)i)/(c + dd/c)
  9. * (a + bi)/(c + di) = (b - ai)/(d - ci)
  10. */
  11. void
  12. cdiv(double a, double b, double c, double d, double *u, double *v)
  13. {
  14. double r,t;
  15. if(fabs(c)<fabs(d)) {
  16. t = -c; c = d; d = t;
  17. t = -a; a = b; b = t;
  18. }
  19. r = d/c;
  20. t = c + r*d;
  21. *u = (a + r*b)/t;
  22. *v = (b - r*a)/t;
  23. }
  24. void
  25. cmul(double c1, double c2, double d1, double d2, double *e1, double *e2)
  26. {
  27. *e1 = c1*d1 - c2*d2;
  28. *e2 = c1*d2 + c2*d1;
  29. }
  30. void
  31. csq(double c1, double c2, double *e1, double *e2)
  32. {
  33. *e1 = c1*c1 - c2*c2;
  34. *e2 = c1*c2*2;
  35. }
  36. /* complex square root
  37. * assumes underflow yields 0.0
  38. * uses these identities:
  39. * sqrt(x+_iy) = sqrt(r(cos(t)+_isin(t))
  40. * = sqrt(r)(cos(t/2)+_isin(t/2))
  41. * cos(t/2) = sin(t)/2sin(t/2) = sqrt((1+cos(t)/2)
  42. * sin(t/2) = sin(t)/2cos(t/2) = sqrt((1-cos(t)/2)
  43. */
  44. void
  45. csqrt(double c1, double c2, double *e1, double *e2)
  46. {
  47. double r,s;
  48. double x,y;
  49. x = fabs(c1);
  50. y = fabs(c2);
  51. if(x>=y) {
  52. if(x==0) {
  53. *e1 = *e2 = 0;
  54. return;
  55. }
  56. r = x;
  57. s = y/x;
  58. } else {
  59. r = y;
  60. s = x/y;
  61. }
  62. r *= sqrt(1+ s*s);
  63. if(c1>0) {
  64. *e1 = sqrt((r+c1)/2);
  65. *e2 = c2/(2* *e1);
  66. } else {
  67. *e2 = sqrt((r-c1)/2);
  68. if(c2<0)
  69. *e2 = -*e2;
  70. *e1 = c2/(2* *e2);
  71. }
  72. }
  73. void cpow(double c1, double c2, double *d1, double *d2, double pwr)
  74. {
  75. double theta = pwr*atan2(c2,c1);
  76. double r = pow(hypot(c1,c2), pwr);
  77. *d1 = r*cos(theta);
  78. *d2 = r*sin(theta);
  79. }