Skip to content

Instantly share code, notes, and snippets.

@Quackward
Created August 29, 2021 10:22
Show Gist options
  • Save Quackward/b01b9373ad446040d5c6de6bc6c70f05 to your computer and use it in GitHub Desktop.
Save Quackward/b01b9373ad446040d5c6de6bc6c70f05 to your computer and use it in GitHub Desktop.
// `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