types_Real.mjs

import {create, copy, compare, size, setStart, setEnd} from "./helpers/common.mjs";

/** Implementation of {@link RangeType} for real values. You can use this to implement any
 * continuous {@link RangeType}, so long as you can map them to the domain of reals. In reality the
 * operations will be using floating point arithmetic. However the assumptions made by the
 * {@link RangeType.compare} method for this type are that each value is a point on a continuous
 * number line.
 * 
 * No {@link RangeType.iterate} implementation is provided, as it represents a continuous type.
 * 
 * The builtin {@link RangeType.sample} method is not perfect. Firstly, we cannot map `[0,1)` to any
 * floating point range, e.g. we can only sample half of the values in `[-1,1]`. Exclusion is only
 * handled properly when the end, and only end, is exclusive. This matches the exclusion of the
 * input `[0,1)`. If the end is inclusive, it won't ever get sampled. If the start is exclusive, it
 * could get falsely sampled. For accurate handling of exclusion, you can consider using the
 * {@link FloatNormType} instead. Another alternative would be to write your own sampler which
 * resamples if the value is exclusive (e.g. perhaps returning null and looping elsewhere until
 * non-null).
 * 
 * Inputs for this type are [coerced to
 * numbers](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number#number_coercion)
 * prior to calculations.
 * @implements {RangeType}
 */
const RealType = {
	create,
	copy,
	setStart,
	setEnd,
	size,
	/** The distance is simply the signed difference: e.g. the distance from start-to-end of
 	 * `[0.25,4.75)` is 4.5, and end-to-start is -4.5. An exclusive bound can be thought of as the
 	 * limit as we approach the value from +∞ (range end) or -∞ (range start). This gives you the
 	 * *sidedness* of a value: e.g. the range end of `[0.5,4.75)` comes before `[0,5,4.75]`.
	 */
	compare(mode, a, b, aExcl, bExcl){
		const out = compare(mode, a, b);
		// handle exclusion
		if (!out.side){
			// similar computation to normalization for discrete case
			out.side = Math.sign(
				(aExcl ? 1 - ((mode & 0b1) << 1) : 0) -
				(bExcl ? 1 - (mode & 0b10) : 0)
			);
		}
		return out;
	},
	sample(range, i){
		return +range.start + i*size(range);
	}
};

export default RealType;