import { assert } from '../../../../../../common/util/util.js';
import { anyOf } from '../../../../../util/compare.js';
import { abstractInt, i32 } from '../../../../../util/conversion.js';
import { FP } from '../../../../../util/floating_point.js';
import { biasedRange, quantizeToI32, sparseI32Range } from '../../../../../util/math.js';
import { Case } from '../../case.js';
import { makeCaseCache } from '../../case_cache.js';
const makeCase = (trait: 'f32' | 'f16' | 'abstract', e1: number, e2: number): Case => {
const FPTrait = FP[trait];
e1 = FPTrait.quantize(e1);
assert(-2147483648 <= e2 && e2 <= 2147483647, 'e2 should be in i32 range');
e2 = quantizeToI32(e2);
const expected = FPTrait.ldexpInterval(e1, e2);
const e2_scalar = trait === 'abstract' ? abstractInt(BigInt(e2)) : i32(e2);
if (e2 + FPTrait.constants().bias <= 0) {
return {
input: [FPTrait.scalarBuilder(e1), e2_scalar],
expected: anyOf(expected, FPTrait.constants().zeroInterval),
};
}
return { input: [FPTrait.scalarBuilder(e1), e2_scalar], expected };
};
const cases = (['f32', 'f16', 'abstract'] as const)
.flatMap(trait =>
([true, false] as const).map(nonConst => ({
[`${trait}_${nonConst ? 'non_const' : 'const'}`]: () => {
if (nonConst) {
if (trait === 'abstract') {
return [];
}
return FP[trait]
.sparseScalarRange()
.flatMap(e1 => sparseI32Range().map(e2 => makeCase(trait, e1, e2)));
}
const bias = FP[trait].constants().bias;
return FP[trait]
.sparseScalarRange()
.flatMap(e1 =>
biasedRange(-bias - 10, bias + 1, 10).flatMap(e2 =>
FP[trait].isFinite(e1 * 2 ** quantizeToI32(e2)) ? makeCase(trait, e1, e2) : []
)
);
},
}))
)
.reduce((a, b) => ({ ...a, ...b }), {});
export const d = makeCaseCache('ldexp', cases);