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