// META: title=validation tests for WebNN API prelu operation // META: global=window // META: variant=?cpu // META: variant=?gpu // META: variant=?npu // META: script=../resources/utils_validation.js 'use strict'; const tests = [ { name: '[quantizeLinear] Test scale\'s shape = [3, 2, 5] and zeroPoint\'s shape = [3, 2, 5] which is the same as input\'s shape.', input: {dataType: 'float32', shape: [3, 2, 5]}, scale: {dataType: 'float32', shape: [3, 2, 5]}, zeroPoint: {dataType: 'int8', shape: [3, 2, 5]}, output: {dataType: 'int8', shape: [3, 2, 5]}, }, { name: '[quantizeLinear] Test scale\'s shape = [5] and zeroPoint\'s shape = [5] which is unidirectionally broadcastable to input\'s shape.', input: {dataType: 'float32', shape: [3, 2, 5]}, scale: {dataType: 'float32', shape: [5]}, zeroPoint: {dataType: 'int8', shape: [5]}, output: {dataType: 'int8', shape: [3, 2, 5]}, }, { name: '[quantizeLinear] Test scale\'s shape = [] and zeroPoint\'s shape = [] which is unidirectionally broadcastable to input\'s shape.', input: {dataType: 'float32', shape: [3, 2, 5]}, scale: {dataType: 'float32', shape: []}, zeroPoint: {dataType: 'int8', shape: []}, output: {dataType: 'int8', shape: [3, 2, 5]}, }, { name: '[quantizeLinear] Test block-wise quantization with block_size = [3, 2, 5].', input: {dataType: 'float32', shape: [6, 4, 5]}, scale: {dataType: 'float32', shape: [2, 2, 1]}, zeroPoint: {dataType: 'int8', shape: [2, 2, 1]}, output: {dataType: 'int8', shape: [6, 4, 5]}, }, { name: '[quantizeLinear] Throw if the scale size is not a factor of input size.', input: {dataType: 'float32', shape: [3, 2, 5]}, scale: {dataType: 'float32', shape: [2, 1, 5]}, zeroPoint: {dataType: 'int8', shape: [2, 1, 5]}, }, { name: '[quantizeLinear] Throw if the shape of zero_point is not the same as the shape of input.', input: {dataType: 'float32', shape: [3, 2, 5]}, scale: {dataType: 'float32', shape: [5]}, zeroPoint: {dataType: 'int8', shape: [2, 5]}, }, { name: '[quantizeLinear] Throw if the data type of input is not the same as scale.', input: {dataType: 'float32', shape: [3, 2, 5]}, scale: {dataType: 'float16', shape: [3, 1, 5]}, zeroPoint: {dataType: 'int8', shape: [3, 1, 5]}, }, { name: '[quantizeLinear] Throw if the data type of input is not float32 or float16.', input: {dataType: 'int32', shape: [3, 2, 5]}, scale: {dataType: 'float32', shape: [5]}, zeroPoint: {dataType: 'int8', shape: [5]}, }, { name: '[quantizeLinear] Throw if the data type of scale is not float32 or float16.', input: {dataType: 'float32', shape: [3, 2, 5]}, scale: {dataType: 'int32', shape: [5]}, zeroPoint: {dataType: 'uint8', shape: [5]}, }, { name: '[quantizeLinear] Throw if the data type of zeroPoint is not int8 or uint8.', input: {dataType: 'float32', shape: [3, 2, 5]}, scale: {dataType: 'float32', shape: [5]}, zeroPoint: {dataType: 'float16', shape: [5]}, }, ]; tests.forEach( test => promise_test(async t => { const builder = new MLGraphBuilder(context); const input = builder.input('input', test.input); const scale = builder.input('scale', test.scale); const zeroPoint = builder.input('zeroPoint', test.zeroPoint); if (test.output) { const output = builder.quantizeLinear(input, scale, zeroPoint); assert_equals(output.dataType, test.output.dataType); assert_array_equals(output.shape, test.output.shape); } else { const label = 'quantize_linear_123'; const options = {label}; const regrexp = new RegExp('\\[' + label + '\\]'); assert_throws_with_label( () => builder.quantizeLinear(input, scale, zeroPoint, options), regrexp); } }, test.name)); const kExampleInputDescriptor = { dataType: 'float32', shape: [2, 4] }; const kExampleZeroPointDescriptor = { dataType: 'int8', shape: [2, 4] }; multi_builder_test(async (t, builder, otherBuilder) => { const inputFromOtherBuilder = otherBuilder.input('input', kExampleInputDescriptor); const scale = builder.input('scale', kExampleInputDescriptor); const zeroPoint = builder.input('zeroPoint', kExampleZeroPointDescriptor); assert_throws_js( TypeError, () => builder.quantizeLinear(inputFromOtherBuilder, scale, zeroPoint)); }, '[quantizeLinear] throw if input is from another builder'); multi_builder_test(async (t, builder, otherBuilder) => { const scaleFromOtherBuilder = otherBuilder.input('scale', kExampleInputDescriptor); const input = builder.input('input', kExampleInputDescriptor); const zeroPoint = builder.input('zeroPoint', kExampleZeroPointDescriptor); assert_throws_js( TypeError, () => builder.quantizeLinear(input, scaleFromOtherBuilder, zeroPoint)); }, '[quantizeLinear] throw if scale is from another builder'); multi_builder_test(async (t, builder, otherBuilder) => { const zeroPointFromOtherBuilder = otherBuilder.input('zeroPoint', kExampleZeroPointDescriptor); const input = builder.input('input', kExampleInputDescriptor); const scale = builder.input('scale', kExampleInputDescriptor); assert_throws_js( TypeError, () => builder.quantizeLinear(input, scale, zeroPointFromOtherBuilder)); }, '[quantizeLinear] throw if zeroPoint is from another builder');