move vector ops page
[libreriscv.git] / simple_v_extension / 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 Pseudocode:
43
44 // Imprecise method, which does not guarantee v = v1 when t = 1,
45 // due to floating-point arithmetic error.
46 // This form may be used when the hardware has a native fused
47 // multiply-add instruction.
48 float lerp(float v0, float v1, float t) {
49 return v0 + t * (v1 - v0);
50 }
51
52 // Precise method, which guarantees v = v1 when t = 1.
53 float lerp(float v0, float v1, float t) {
54 return (1 - t) * v0 + t * v1;
55 }
56
57 ## Vector SLERP
58
59 <https://en.m.wikipedia.org/wiki/Slerp>
60
61 Pseudocode:
62
63 Quaternion slerp(Quaternion v0, Quaternion v1, double t) {
64 // Only unit quaternions are valid rotations.
65 // Normalize to avoid undefined behavior.
66 v0.normalize();
67 v1.normalize();
68
69 // Compute the cosine of the angle between the two vectors.
70 double dot = dot_product(v0, v1);
71
72 // If the dot product is negative, slerp won't take
73 // the shorter path. Note that v1 and -v1 are equivalent when
74 // the negation is applied to all four components. Fix by
75 // reversing one quaternion.
76 if (dot < 0.0f) {
77 v1 = -v1;
78 dot = -dot;
79 }
80
81 const double DOT_THRESHOLD = 0.9995;
82 if (dot > DOT_THRESHOLD) {
83 // If the inputs are too close for comfort, linearly interpolate
84 // and normalize the result.
85
86 Quaternion result = v0 + t*(v1 - v0);
87 result.normalize();
88 return result;
89 }
90
91 // Since dot is in range [0, DOT_THRESHOLD], acos is safe
92 double theta_0 = acos(dot); // theta_0 = angle between input vectors
93 double theta = theta_0*t; // theta = angle between v0 and result
94 double sin_theta = sin(theta); // compute this value only once
95 double sin_theta_0 = sin(theta_0); // compute this value only once
96
97 double s0 = cos(theta) - dot * sin_theta / sin_theta_0; // == sin(theta_0 - theta) / sin(theta_0)
98 double s1 = sin_theta / sin_theta_0;
99
100 return (s0 * v0) + (s1 * v1);
101 }