Yosun's picture
Deploy TripoSplat WebGPU demo
31c7d49 verified
Raw
History Blame Contribute Delete
2.45 kB
export function layerNormRows(
input: Float32Array,
width: number,
epsilon = 1e-5,
): Float32Array {
if (!Number.isInteger(width) || width <= 0 || input.length % width !== 0) {
throw new Error(`layerNormRows width ${width} does not divide input length ${input.length}.`)
}
const output = new Float32Array(input.length)
for (let offset = 0; offset < input.length; offset += width) {
let mean = 0
for (let index = 0; index < width; index += 1) mean += input[offset + index]
mean /= width
let variance = 0
for (let index = 0; index < width; index += 1) {
const centered = input[offset + index] - mean
variance += centered * centered
}
const inverseStandardDeviation = 1 / Math.sqrt(variance / width + epsilon)
for (let index = 0; index < width; index += 1) {
output[offset + index] = (input[offset + index] - mean) * inverseStandardDeviation
}
}
return output
}
export interface TensorComparison {
count: number
maxAbsoluteError: number
meanAbsoluteError: number
rmse: number
cosineSimilarity: number
finite: boolean
}
export function compareFloat32(reference: Float32Array, candidate: Float32Array): TensorComparison {
if (reference.length !== candidate.length) {
throw new Error(`Tensor lengths differ: reference=${reference.length}, candidate=${candidate.length}.`)
}
let maxAbsoluteError = 0
let absoluteErrorSum = 0
let squaredErrorSum = 0
let dot = 0
let referenceSquared = 0
let candidateSquared = 0
let finite = true
for (let index = 0; index < reference.length; index += 1) {
const expected = reference[index]
const actual = candidate[index]
if (!Number.isFinite(expected) || !Number.isFinite(actual)) finite = false
const delta = actual - expected
const absolute = Math.abs(delta)
maxAbsoluteError = Math.max(maxAbsoluteError, absolute)
absoluteErrorSum += absolute
squaredErrorSum += delta * delta
dot += expected * actual
referenceSquared += expected * expected
candidateSquared += actual * actual
}
const denominator = Math.sqrt(referenceSquared * candidateSquared)
return {
count: reference.length,
maxAbsoluteError,
meanAbsoluteError: reference.length > 0 ? absoluteErrorSum / reference.length : 0,
rmse: reference.length > 0 ? Math.sqrt(squaredErrorSum / reference.length) : 0,
cosineSimilarity: denominator > 0 ? dot / denominator : 1,
finite,
}
}