# 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. 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 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); }