quantizeLinear.https.any.js (5837B)
1 // META: title=validation tests for WebNN API prelu operation 2 // META: global=window 3 // META: variant=?cpu 4 // META: variant=?gpu 5 // META: variant=?npu 6 // META: script=../resources/utils_validation.js 7 8 'use strict'; 9 10 const tests = [ 11 { 12 name: 13 '[quantizeLinear] Test scale\'s shape = [3, 2, 5] and zeroPoint\'s shape = [3, 2, 5] which is the same as input\'s shape.', 14 input: {dataType: 'float32', shape: [3, 2, 5]}, 15 scale: {dataType: 'float32', shape: [3, 2, 5]}, 16 zeroPoint: {dataType: 'int8', shape: [3, 2, 5]}, 17 output: {dataType: 'int8', shape: [3, 2, 5]}, 18 }, 19 { 20 name: 21 '[quantizeLinear] Test scale\'s shape = [1, 1, 5] and zeroPoint\'s shape = [1, 1, 5] which is unidirectionally broadcastable to input\'s shape.', 22 input: {dataType: 'float32', shape: [3, 2, 5]}, 23 scale: {dataType: 'float32', shape: [1, 1, 5]}, 24 zeroPoint: {dataType: 'int8', shape: [1, 1, 5]}, 25 output: {dataType: 'int8', shape: [3, 2, 5]}, 26 }, 27 { 28 name: 29 '[quantizeLinear] Test scale\'s shape = [1, 1, 1] and zeroPoint\'s shape = [1, 1, 1] which is unidirectionally broadcastable to input\'s shape.', 30 input: {dataType: 'float32', shape: [3, 2, 5]}, 31 scale: {dataType: 'float32', shape: [1, 1, 1]}, 32 zeroPoint: {dataType: 'int8', shape: [1, 1, 1]}, 33 output: {dataType: 'int8', shape: [3, 2, 5]}, 34 }, 35 { 36 name: 37 '[quantizeLinear] Test block-wise quantization with block_size = [3, 2, 5].', 38 input: {dataType: 'float32', shape: [6, 4, 5]}, 39 scale: {dataType: 'float32', shape: [2, 2, 1]}, 40 zeroPoint: {dataType: 'int8', shape: [2, 2, 1]}, 41 output: {dataType: 'int8', shape: [6, 4, 5]}, 42 }, 43 { 44 name: 45 '[quantizeLinear] Throw if the scale rank is not equal to input rank.', 46 input: {dataType: 'float32', shape: [3, 2, 5]}, 47 scale: {dataType: 'float32', shape: [5]}, 48 zeroPoint: {dataType: 'int8', shape: [5]}, 49 }, 50 { 51 name: 52 '[quantizeLinear] Throw if the scale size is not a factor of input size.', 53 input: {dataType: 'float32', shape: [3, 2, 5]}, 54 scale: {dataType: 'float32', shape: [2, 1, 5]}, 55 zeroPoint: {dataType: 'int8', shape: [2, 1, 5]}, 56 }, 57 { 58 name: 59 '[quantizeLinear] Throw if the shape of zero_point is not the same as the shape of input.', 60 input: {dataType: 'float32', shape: [3, 2, 5]}, 61 scale: {dataType: 'float32', shape: [5]}, 62 zeroPoint: {dataType: 'int8', shape: [2, 5]}, 63 }, 64 { 65 name: 66 '[quantizeLinear] Throw if the data type of input is not the same as scale.', 67 input: {dataType: 'float32', shape: [3, 2, 5]}, 68 scale: {dataType: 'float16', shape: [3, 1, 5]}, 69 zeroPoint: {dataType: 'int8', shape: [3, 1, 5]}, 70 }, 71 { 72 name: 73 '[quantizeLinear] Throw if the data type of input is not float32 or float16.', 74 input: {dataType: 'int32', shape: [3, 2, 5]}, 75 scale: {dataType: 'float32', shape: [5]}, 76 zeroPoint: {dataType: 'int8', shape: [5]}, 77 }, 78 { 79 name: 80 '[quantizeLinear] Throw if the data type of scale is not float32 or float16.', 81 input: {dataType: 'float32', shape: [3, 2, 5]}, 82 scale: {dataType: 'int32', shape: [5]}, 83 zeroPoint: {dataType: 'uint8', shape: [5]}, 84 }, 85 { 86 name: 87 '[quantizeLinear] Throw if the data type of zeroPoint is not int8 or uint8.', 88 input: {dataType: 'float32', shape: [3, 2, 5]}, 89 scale: {dataType: 'float32', shape: [5]}, 90 zeroPoint: {dataType: 'float16', shape: [5]}, 91 }, 92 ]; 93 94 tests.forEach( 95 test => promise_test(async t => { 96 const builder = new MLGraphBuilder(context); 97 const input = builder.input('input', test.input); 98 const scale = builder.input('scale', test.scale); 99 const zeroPoint = builder.input('zeroPoint', test.zeroPoint); 100 if (test.output) { 101 const output = builder.quantizeLinear(input, scale, zeroPoint); 102 assert_equals(output.dataType, test.output.dataType); 103 assert_array_equals(output.shape, test.output.shape); 104 } else { 105 const label = 'quantize_linear_123'; 106 const options = {label}; 107 const regrexp = new RegExp('\\[' + label + '\\]'); 108 assert_throws_with_label( 109 () => builder.quantizeLinear(input, scale, zeroPoint, options), 110 regrexp); 111 } 112 }, test.name)); 113 114 const kExampleInputDescriptor = { 115 dataType: 'float32', 116 shape: [2, 4] 117 }; 118 const kExampleZeroPointDescriptor = { 119 dataType: 'int8', 120 shape: [2, 4] 121 }; 122 multi_builder_test(async (t, builder, otherBuilder) => { 123 const inputFromOtherBuilder = 124 otherBuilder.input('input', kExampleInputDescriptor); 125 126 const scale = builder.input('scale', kExampleInputDescriptor); 127 const zeroPoint = builder.input('zeroPoint', kExampleZeroPointDescriptor); 128 assert_throws_js( 129 TypeError, 130 () => builder.quantizeLinear(inputFromOtherBuilder, scale, zeroPoint)); 131 }, '[quantizeLinear] throw if input is from another builder'); 132 133 multi_builder_test(async (t, builder, otherBuilder) => { 134 const scaleFromOtherBuilder = 135 otherBuilder.input('scale', kExampleInputDescriptor); 136 137 const input = builder.input('input', kExampleInputDescriptor); 138 const zeroPoint = builder.input('zeroPoint', kExampleZeroPointDescriptor); 139 assert_throws_js( 140 TypeError, 141 () => builder.quantizeLinear(input, scaleFromOtherBuilder, zeroPoint)); 142 }, '[quantizeLinear] throw if scale is from another builder'); 143 144 multi_builder_test(async (t, builder, otherBuilder) => { 145 const zeroPointFromOtherBuilder = 146 otherBuilder.input('zeroPoint', kExampleZeroPointDescriptor); 147 148 const input = builder.input('input', kExampleInputDescriptor); 149 const scale = builder.input('scale', kExampleInputDescriptor); 150 assert_throws_js( 151 TypeError, 152 () => builder.quantizeLinear(input, scale, zeroPointFromOtherBuilder)); 153 }, '[quantizeLinear] throw if zeroPoint is from another builder');