import { ROArrayArray } from '../../../../../../common/util/types.js';
import { anyOf } from '../../../../../util/compare.js';
import { toVector } from '../../../../../util/conversion.js';
import { FP, FPKind, FPVector } from '../../../../../util/floating_point.js';
import { cartesianProduct } from '../../../../../util/math.js';
import { Case, selectNCases } from '../../case.js';
import { makeCaseCache } from '../../case_cache.js';
import { IntervalFilter } from '../../interval_filter.js';
* @returns a Case for `faceForward`
* @param argumentKind what kind of floating point numbers being operated on
* @param parameterKind what kind of floating point operation should be performed,
* should be the same as argumentKind, except for abstract
* @param x the `x` param for the case
* @param y the `y` param for the case
* @param z the `z` param for the case
* @param check what interval checking to apply
* */
function makeCase(
argumentKind: FPKind,
parameterKind: FPKind,
x: readonly number[],
y: readonly number[],
z: readonly number[],
check: IntervalFilter
): Case | undefined {
const fp = FP[argumentKind];
x = x.map(fp.quantize);
y = y.map(fp.quantize);
z = z.map(fp.quantize);
const results = FP[parameterKind].faceForwardIntervals(x, y, z);
if (check === 'finite' && results.some(r => r === undefined)) {
return undefined;
}
const define_results = results.filter((r): r is FPVector => r !== undefined);
return {
input: [
toVector(x, fp.scalarBuilder),
toVector(y, fp.scalarBuilder),
toVector(z, fp.scalarBuilder),
],
expected: anyOf(...define_results),
};
}
* @returns an array of Cases for `faceForward`
* @param argumentKind what kind of floating point numbers being operated on
* @param parameterKind what kind of floating point operation should be performed,
* should be the same as argumentKind, except for abstract
* @param xs array of inputs to try for the `x` param
* @param ys array of inputs to try for the `y` param
* @param zs array of inputs to try for the `z` param
* @param check what interval checking to apply
*/
function generateCases(
argumentKind: FPKind,
parameterKind: FPKind,
xs: ROArrayArray<number>,
ys: ROArrayArray<number>,
zs: ROArrayArray<number>,
check: IntervalFilter
): Case[] {
return cartesianProduct(xs, ys, zs)
.map(e => makeCase(argumentKind, parameterKind, e[0], e[1], e[2], check))
.filter((c): c is Case => c !== undefined);
}
const cases = (['f32', 'f16', 'abstract'] as const)
.flatMap(trait =>
([2, 3, 4] as const).flatMap(dim =>
([true, false] as const).map(nonConst => ({
[`${trait}_vec${dim}_${nonConst ? 'non_const' : 'const'}`]: () => {
if (trait === 'abstract' && nonConst) {
return [];
}
if (trait !== 'abstract') {
return generateCases(
trait,
trait,
FP[trait].sparseVectorRange(dim),
FP[trait].sparseVectorRange(dim),
FP[trait].sparseVectorRange(dim),
nonConst ? 'unfiltered' : 'finite'
);
} else {
return selectNCases(
'faceForward',
20,
generateCases(
trait,
'f32',
FP[trait].sparseVectorRange(dim),
FP[trait].sparseVectorRange(dim),
FP[trait].sparseVectorRange(dim),
nonConst ? 'unfiltered' : 'finite'
)
);
}
},
}))
)
)
.reduce((a, b) => ({ ...a, ...b }), {});
export const d = makeCaseCache('faceForward', cases);