arcdot.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /* arcdot.c
  2. *
  3. * Angle between two vectors
  4. *
  5. *
  6. *
  7. *
  8. * SYNOPSIS:
  9. *
  10. * double p[3], q[3], arcdot();
  11. *
  12. * y = arcdot( p, q );
  13. *
  14. *
  15. *
  16. * DESCRIPTION:
  17. *
  18. * For two vectors p, q, the angle A between them is given by
  19. *
  20. * p.q / (|p| |q|) = cos A .
  21. *
  22. * where "." represents inner product, "|x|" the length of vector x.
  23. * If the angle is small, an expression in sin A is preferred.
  24. * Set r = q - p. Then
  25. *
  26. * p.q = p.p + p.r ,
  27. *
  28. * |p|^2 = p.p ,
  29. *
  30. * |q|^2 = p.p + 2 p.r + r.r ,
  31. *
  32. * p.p^2 + 2 p.p p.r + p.r^2
  33. * cos^2 A = ----------------------------
  34. * p.p (p.p + 2 p.r + r.r)
  35. *
  36. * p.p + 2 p.r + p.r^2 / p.p
  37. * = --------------------------- ,
  38. * p.p + 2 p.r + r.r
  39. *
  40. * sin^2 A = 1 - cos^2 A
  41. *
  42. * r.r - p.r^2 / p.p
  43. * = --------------------
  44. * p.p + 2 p.r + r.r
  45. *
  46. * = (r.r - p.r^2 / p.p) / q.q .
  47. *
  48. * ACCURACY:
  49. *
  50. * Relative error:
  51. * arithmetic domain # trials peak rms
  52. * IEEE -1, 1 10^6 1.7e-16 4.2e-17
  53. *
  54. */
  55. /*
  56. Cephes Math Library Release 2.3: November, 1995
  57. Copyright 1995 by Stephen L. Moshier
  58. */
  59. #include <math.h>
  60. #ifdef ANSIPROT
  61. extern double sqrt ( double );
  62. extern double acos ( double );
  63. extern double asin ( double );
  64. extern double atan ( double );
  65. #else
  66. double sqrt(), acos(), asin(), atan();
  67. #endif
  68. extern double PI;
  69. double arcdot(p,q)
  70. double p[], q[];
  71. {
  72. double pp, pr, qq, rr, rt, pt, qt, pq;
  73. int i;
  74. pq = 0.0;
  75. qq = 0.0;
  76. pp = 0.0;
  77. pr = 0.0;
  78. rr = 0.0;
  79. for (i=0; i<3; i++)
  80. {
  81. pt = p[i];
  82. qt = q[i];
  83. pq += pt * qt;
  84. qq += qt * qt;
  85. pp += pt * pt;
  86. rt = qt - pt;
  87. pr += pt * rt;
  88. rr += rt * rt;
  89. }
  90. if (rr == 0.0 || pp == 0.0 || qq == 0.0)
  91. return 0.0;
  92. rt = (rr - (pr * pr) / pp) / qq;
  93. if (rt <= 0.75)
  94. {
  95. rt = sqrt(rt);
  96. qt = asin(rt);
  97. if (pq < 0.0)
  98. qt = PI - qt;
  99. }
  100. else
  101. {
  102. pt = pq / sqrt(pp*qq);
  103. qt = acos(pt);
  104. }
  105. return qt;
  106. }