--- /dev/null
+# Vector Operations Extension to SV
+
+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.
+
+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.
+
+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.
+
+Examples which can require SUBVL include cross product and may in future involve complex numbers.
+
+## Vector cross product
+
+Result is the cross product of x and y, i.e., the resulting components are, in order:
+
+ x[1] * y[2] - y[1] * x[2]
+ x[2] * y[0] - y[2] * x[0]
+ x[0] * y[1] - y[0] * x[1]
+
+All the operands must be vectors of 3 components of a floating-point type.
+
+## Vector dot product
+
+Computes the dot product of two vectors. Internal accuracy must be greater than the
+input vectors and the result.
+
+## Vector length
+
+The scalar length of a vector:
+
+ sqrt(x[0]^2 + x[1]^2 + ...).
+
+## Vector distance
+
+The scalar distance between two vectors. Subtracts one vector from the other and returns length
+
+## Vector LERP
+
+Known as **fmix** in GLSL.
+
+<https://en.m.wikipedia.org/wiki/Linear_interpolation>
+
+Pseudocode:
+
+ // Imprecise method, which does not guarantee v = v1 when t = 1,
+ // due to floating-point arithmetic error.
+ // This form may be used when the hardware has a native fused
+ // multiply-add instruction.
+ float lerp(float v0, float v1, float t) {
+ return v0 + t * (v1 - v0);
+ }
+
+ // Precise method, which guarantees v = v1 when t = 1.
+ float lerp(float v0, float v1, float t) {
+ return (1 - t) * v0 + t * v1;
+ }
+
+## Vector SLERP
+
+<https://en.m.wikipedia.org/wiki/Slerp>
+
+Pseudocode:
+
+ Quaternion slerp(Quaternion v0, Quaternion v1, double t) {
+ // Only unit quaternions are valid rotations.
+ // Normalize to avoid undefined behavior.
+ v0.normalize();
+ v1.normalize();
+
+ // Compute the cosine of the angle between the two vectors.
+ double dot = dot_product(v0, v1);
+
+ // If the dot product is negative, slerp won't take
+ // the shorter path. Note that v1 and -v1 are equivalent when
+ // the negation is applied to all four components. Fix by
+ // reversing one quaternion.
+ if (dot < 0.0f) {
+ v1 = -v1;
+ dot = -dot;
+ }
+
+ const double DOT_THRESHOLD = 0.9995;
+ if (dot > DOT_THRESHOLD) {
+ // If the inputs are too close for comfort, linearly interpolate
+ // and normalize the result.
+
+ Quaternion result = v0 + t*(v1 - v0);
+ result.normalize();
+ return result;
+ }
+
+ // Since dot is in range [0, DOT_THRESHOLD], acos is safe
+ double theta_0 = acos(dot); // theta_0 = angle between input vectors
+ double theta = theta_0*t; // theta = angle between v0 and result
+ double sin_theta = sin(theta); // compute this value only once
+ double sin_theta_0 = sin(theta_0); // compute this value only once
+
+ double s0 = cos(theta) - dot * sin_theta / sin_theta_0; // == sin(theta_0 - theta) / sin(theta_0)
+ double s1 = sin_theta / sin_theta_0;
+
+ return (s0 * v0) + (s1 * v1);
+ }
+++ /dev/null
-# Vector Operations Extension to SV
-
-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.
-
-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.
-
-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.
-
-Examples which can require SUBVL include cross product and may in future involve complex numbers.
-
-## Vector cross product
-
-Result is the cross product of x and y, i.e., the resulting components are, in order:
-
- x[1] * y[2] - y[1] * x[2]
- x[2] * y[0] - y[2] * x[0]
- x[0] * y[1] - y[0] * x[1]
-
-All the operands must be vectors of 3 components of a floating-point type.
-
-## Vector dot product
-
-Computes the dot product of two vectors. Internal accuracy must be greater than the
-input vectors and the result.
-
-## Vector length
-
-The scalar length of a vector:
-
- sqrt(x[0]^2 + x[1]^2 + ...).
-
-## Vector distance
-
-The scalar distance between two vectors. Subtracts one vector from the other and returns length
-
-## Vector LERP
-
-Known as **fmix** in GLSL.
-
-<https://en.m.wikipedia.org/wiki/Linear_interpolation>
-
-Pseudocode:
-
- // Imprecise method, which does not guarantee v = v1 when t = 1,
- // due to floating-point arithmetic error.
- // This form may be used when the hardware has a native fused
- // multiply-add instruction.
- float lerp(float v0, float v1, float t) {
- return v0 + t * (v1 - v0);
- }
-
- // Precise method, which guarantees v = v1 when t = 1.
- float lerp(float v0, float v1, float t) {
- return (1 - t) * v0 + t * v1;
- }
-
-## Vector SLERP
-
-<https://en.m.wikipedia.org/wiki/Slerp>
-
-Pseudocode:
-
- Quaternion slerp(Quaternion v0, Quaternion v1, double t) {
- // Only unit quaternions are valid rotations.
- // Normalize to avoid undefined behavior.
- v0.normalize();
- v1.normalize();
-
- // Compute the cosine of the angle between the two vectors.
- double dot = dot_product(v0, v1);
-
- // If the dot product is negative, slerp won't take
- // the shorter path. Note that v1 and -v1 are equivalent when
- // the negation is applied to all four components. Fix by
- // reversing one quaternion.
- if (dot < 0.0f) {
- v1 = -v1;
- dot = -dot;
- }
-
- const double DOT_THRESHOLD = 0.9995;
- if (dot > DOT_THRESHOLD) {
- // If the inputs are too close for comfort, linearly interpolate
- // and normalize the result.
-
- Quaternion result = v0 + t*(v1 - v0);
- result.normalize();
- return result;
- }
-
- // Since dot is in range [0, DOT_THRESHOLD], acos is safe
- double theta_0 = acos(dot); // theta_0 = angle between input vectors
- double theta = theta_0*t; // theta = angle between v0 and result
- double sin_theta = sin(theta); // compute this value only once
- double sin_theta_0 = sin(theta_0); // compute this value only once
-
- double s0 = cos(theta) - dot * sin_theta / sin_theta_0; // == sin(theta_0 - theta) / sin(theta_0)
- double s1 = sin_theta / sin_theta_0;
-
- return (s0 * v0) + (s1 * v1);
- }