From: Luke Kenneth Casson Leighton Date: Mon, 16 Sep 2019 08:13:25 +0000 (+0100) Subject: move vector ops page X-Git-Tag: convert-csv-opcode-to-binary~4045 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=97ed852a3999a9cdcea76d725adc561a1024ca4c;p=libreriscv.git move vector ops page --- diff --git a/simple_v_extension/vector_ops.mdwn b/simple_v_extension/vector_ops.mdwn new file mode 100644 index 000000000..11235f24e --- /dev/null +++ b/simple_v_extension/vector_ops.mdwn @@ -0,0 +1,101 @@ +# 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); + } diff --git a/vector_ops.mdwn b/vector_ops.mdwn deleted file mode 100644 index 11235f24e..000000000 --- a/vector_ops.mdwn +++ /dev/null @@ -1,101 +0,0 @@ -# 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); - }