(no commit message)
[libreriscv.git] / vector_ops.mdwn
1 # Vector Operations Extension to SV
2
3 This extension is usually dependent on SV SUBVL being implemented. When SUBVL is set to define the length of a subvector the operations in this extension interpret the elements as a single vector.
4
5 Normally in SV all operations are scalar and independent, and the operations on them may inherently be independently parallelised, with the result being a vector of length exactly equal to the input vectors.
6
7 In this extension, the subvector itself is typically the unit, although some operations will work on scalars or standard vectors as well, or the result is a scalar that is dependent on all elements within the vector arguments.
8
9 Examples which can require SUBVL include cross product and may in future involve complex numbers.
10
11 ## Vector cross product
12
13 Result is the cross product of x and y, i.e., the resulting components are, in order:
14
15 x[1] * y[2] - y[1] * x[2]
16 x[2] * y[0] - y[2] * x[0]
17 x[0] * y[1] - y[0] * x[1]
18
19 All the operands must be vectors of 3 components of a floating-point type.
20
21 ## Vector dot product
22
23 Computes the dot product of two vectors. Internal accuracy must be greater than the
24 input vectors and the result.
25
26 ## Vector length
27
28 The scalar length of a vector:
29
30 sqrt(x[0]^2 + x[1]^2 + ...).
31
32 ## Vector distance
33
34 The scalar distance between two vectors. Subtracts one vector from the other and returns length
35
36 ## Vector LERP
37
38 Known as **fmix** in GLSL.
39
40 <https://en.m.wikipedia.org/wiki/Linear_interpolation>
41
42 ## Vector SLERP
43
44 <https://en.m.wikipedia.org/wiki/Slerp>
45
46 """
47 Quaternion slerp(Quaternion v0, Quaternion v1, double t) {
48 // Only unit quaternions are valid rotations.
49 // Normalize to avoid undefined behavior.
50 v0.normalize();
51 v1.normalize();
52
53 // Compute the cosine of the angle between the two vectors.
54 double dot = dot_product(v0, v1);
55
56 // If the dot product is negative, slerp won't take
57 // the shorter path. Note that v1 and -v1 are equivalent when
58 // the negation is applied to all four components. Fix by
59 // reversing one quaternion.
60 if (dot < 0.0f) {
61 v1 = -v1;
62 dot = -dot;
63 }
64
65 const double DOT_THRESHOLD = 0.9995;
66 if (dot > DOT_THRESHOLD) {
67 // If the inputs are too close for comfort, linearly interpolate
68 // and normalize the result.
69
70 Quaternion result = v0 + t*(v1 - v0);
71 result.normalize();
72 return result;
73 }
74
75 // Since dot is in range [0, DOT_THRESHOLD], acos is safe
76 double theta_0 = acos(dot); // theta_0 = angle between input vectors
77 double theta = theta_0*t; // theta = angle between v0 and result
78 double sin_theta = sin(theta); // compute this value only once
79 double sin_theta_0 = sin(theta_0); // compute this value only once
80
81 double s0 = cos(theta) - dot * sin_theta / sin_theta_0; // == sin(theta_0 - theta) / sin(theta_0)
82 double s1 = sin_theta / sin_theta_0;
83
84 return (s0 * v0) + (s1 * v1);
85 }
86 """