arcdotl.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /* arcdot.c
  2. *
  3. * Angle between two vectors
  4. *
  5. *
  6. *
  7. *
  8. * SYNOPSIS:
  9. *
  10. * long double p[3], q[3], arcdotl();
  11. *
  12. * y = arcdotl( 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. * About 1 ULP. See arcdot.c.
  51. *
  52. */
  53. /*
  54. Cephes Math Library Release 2.3: November, 1995
  55. Copyright 1995 by Stephen L. Moshier
  56. */
  57. #include <math.h>
  58. #ifdef ANSIPROT
  59. extern long double sqrtl ( long double );
  60. extern long double acosl ( long double );
  61. extern long double asinl ( long double );
  62. extern long double atanl ( long double );
  63. #else
  64. long double sqrtl(), acosl(), asinl(), atanl();
  65. #endif
  66. extern long double PIL;
  67. long double arcdotl(p,q)
  68. long double p[], q[];
  69. {
  70. long double pp, pr, qq, rr, rt, pt, qt, pq;
  71. int i;
  72. pq = 0.0L;
  73. qq = 0.0L;
  74. pp = 0.0L;
  75. pr = 0.0L;
  76. rr = 0.0L;
  77. for (i=0; i<3; i++)
  78. {
  79. pt = p[i];
  80. qt = q[i];
  81. pq += pt * qt;
  82. qq += qt * qt;
  83. pp += pt * pt;
  84. rt = qt - pt;
  85. pr += pt * rt;
  86. rr += rt * rt;
  87. }
  88. if (rr == 0.0L || pp == 0.0L || qq == 0.0L)
  89. return 0.0L;
  90. rt = (rr - (pr * pr) / pp) / qq;
  91. if (rt <= 0.75L)
  92. {
  93. rt = sqrtl(rt);
  94. qt = asinl(rt);
  95. if (pq < 0.0L)
  96. qt = PIL - qt;
  97. }
  98. else
  99. {
  100. pt = pq / sqrtl(pp*qq);
  101. qt = acosl(pt);
  102. }
  103. return qt;
  104. }