Created
August 29, 2021 10:22
-
-
Save Quackward/b01b9373ad446040d5c6de6bc6c70f05 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// `Ratio` :: fixed point type representing values [0.0 to 1.0] | |
// + automatic bounds clamping | |
// + linear distribution of values, aligned to map cleanly with 1/2^n fractions | |
// - sacrifices ~1 bit of entropy;has no division operator | |
// | |
// Exponent | |
// | ___Mantissa___ if exponent is 1, the value is [1.0] ignoring mantissa | |
// | | | mantissa is always cleared if an operation produces 1.0 | |
// 0 0 0 0 0... 0 0 0 | |
// | | | etc... if exponent is 0, the value is [0.0 to 1.0 - epsilon] | |
// | | +1/8 depending on the mantissa, where each bit adds: | |
// | +1/4 ` 1/2^bitIndex `, where bitIndex starts at 1 | |
// +1/2 | |
// | |
// add (simple integer addition) | |
// (if exponent is 1 on either operand or the result, clear mantissa) | |
// sub (simple integer subtraction) | |
// (if exponent is 1 on rhs operand or the result, clear everything) | |
// mul (simple [to a computer] fixed point multiplication) | |
// (this operation will never set the exponent if neither operand has it set) | |
// (if exponent is 1 in either operand, this returns the opposite operand) | |
// div doesn't exist for this type, a promotion to float is required | |
// div HOWEVER can produce an accurate float reciprical quickly, and multiply the | |
// dividend by that instead, as a potential shortcut when used as a divisor | |
// float promotion is trivial: | |
// exponent ? 1.0f : (1.0f | mantissa<<(23-bitsize)) - 1.0f; | |
// | |
//-------------------------------------------------------------------------------------------------- | |
// | |
// `Turn` :: a type representing a circular range through 0.0 to +/-1.0 and back | |
// range is less like a number LINE and more like a number CIRCLE (think angles): | |
// +/-0.0 and +/-1.0 are opposed, and +0.5 and -0.5 are similarly opposed; | |
// | |
// +0.5 | |
// o O o | |
// +0.25 O O +0.75 | |
// o o | |
// o o | |
// +/-0.0 O o ------- O +/-1.0 | |
// o o | |
// o o | |
// -0.25 o o -0.75 | |
// O o O | |
// -0.5 | |
// | |
// USES | |
// > as normals with acceptable fidelity using 2x 8bit or 16bit Turns (theta and phi) | |
// > as trig function inputs with built-in bounds and usable directly as LUT index | |
// | |
// PROS | |
// + well defined overflow and underflow | |
// + linear distribution of values, aligned to map cleanly with 1/2^n fractions | |
// + sacrifices 0 entropy, no special cases, all values are valid | |
// + 32-bit, 16-bit, and 8-bit precisions | |
// + float promotion is free | |
// + accurate float reciprical free; allows for fast division if Ratio is the divisor | |
// CONS | |
// - +/- 1.0 is an odd concept to grasp, has no satisfying mapping in float | |
// - division with float operand must convert to float and use float division | |
// | |
// Sign | |
// | ___Mantissa___ if sign is 0, the value is [`+/-0.0` to `1.0 - epsilon`] | |
// | | | if sign is 1, the value is [`+/-1.0` to `0.0 - epsilon`] | |
// 0 0 0 0 0... 0 0 0 | |
// | | | etc... value is the mantissa, where each bit adds: | |
// | | +1/8 ` 1/(2^bitIndex) `, where bitIndex starts at 1 | |
// | +1/4 if sign is set, -1.0 is deducted from the value | |
// +1/2 1.0 has no sign, positive or negative. | |
// | |
// operators: | |
// add (simple integer addition with 2's compliment overflow) | |
// | |
// sub (simple integer subtraction with 2's compliment underflow) | |
// | |
// mul (simple [to a computer] fixed point multiplication) | |
// (if either operand is +/- 1.0, return the other operand) | |
// (if either operand is +/- 0.0, return 0.0) | |
// (else this operation sets the result's sign to XOR of both operand signs) | |
// | |
// div doesn't exist for this type, without promotion to float | |
// HOWEVER, can produce an accurate float reciprical quickly, and multiply the | |
// dividend by that instead, as a fast shortcut when used as a divisor | |
// | |
// float promotion is trivial, though +/- 1 is an unusual case with no analog, | |
// (maybe best to assign that the identity value +1) | |
// ~value ? 1.0f : | |
// sign ? (((1.0f | mantissa<<(23-bitsize)) - 1.0f) | (1<<(bitwidth-1))) | |
// : ((1.0f | mantissa<<(23-bitsize)) - 1.0f); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment