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