// META: title=test WebNN API element-wise add operation
// META: global=window,dedicatedworker
// META: variant=?cpu
// META: variant=?gpu
// META: variant=?npu
// META: script=../resources/utils.js
// META: timeout=long
'use strict';
// https://www.w3.org/TR/webnn/#api-mlgraphbuilder-binary
// Compute the element-wise binary addition of the two input tensors.
// MLOperand add(MLOperand a, MLOperand b);
const getAddPrecisionTolerance = (graphResources) => {
const toleranceValueDict = {float32: 1, float16: 1};
const expectedDataType =
getExpectedDataTypeOfSingleOutput(graphResources.expectedOutputs);
return {metricType: 'ULP', value: toleranceValueDict[expectedDataType]};
};
const addTests = [
{
'name': 'add float32 1D constant tensors',
'graph': {
'inputs': {
'inputA': {
'data': [
-43.333316802978516, -67.89795684814453, 26.462739944458008,
36.74276351928711, -65.1773910522461, -87.70664978027344,
65.27881622314453, -74.05226135253906, -13.827810287475586,
6.981486797332764, 99.83751678466797, 55.802337646484375,
-75.57196044921875, 11.499507904052734, 17.110109329223633,
95.81167602539062, 57.4474983215332, -57.175872802734375,
27.719053268432617, -18.219209671020508, 52.653099060058594,
-69.99455261230469, 39.8216552734375, -29.986528396606445
],
'descriptor': {'dimensions': [24], 'dataType': 'float32'},
'constant': true
},
'inputB': {
'data': [
-59.749725341796875, -44.81494140625, -87.93879699707031,
1.8843363523483276, 84.89464569091797, 47.553653717041016,
85.64292907714844, 43.02861404418945, -60.25821304321289,
15.60616683959961, 70.60614776611328, -7.454866409301758,
-30.20689582824707, -97.69825744628906, -0.00984330102801323,
-77.67960357666016, 30.196685791015625, -59.19007110595703,
89.3588638305664, 28.6798095703125, -29.72130584716797,
-90.6352310180664, 28.2818546295166, 27.662540435791016
],
'descriptor': {'dimensions': [24], 'dataType': 'float32'},
'constant': true
}
},
'operators': [{
'name': 'add',
'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
'outputs': 'output'
}],
'expectedOutputs': {
'output': {
'data': [
-103.08303833007812, -112.71289825439453, -61.47605895996094,
38.627098083496094, 19.717254638671875, -40.15299606323242,
150.9217529296875, -31.02364730834961, -74.08602142333984,
22.58765411376953, 170.44366455078125, 48.34747314453125,
-105.77885437011719, -86.19874572753906, 17.100265502929688,
18.13207244873047, 87.64418029785156, -116.3659439086914,
117.07791900634766, 10.460599899291992, 22.931793212890625,
-160.62979125976562, 68.10350799560547, -2.3239879608154297
],
'descriptor': {'dimensions': [24], 'dataType': 'float32'}
}
}
}
},
{
'name': 'add float32 1D tensors',
'graph': {
'inputs': {
'inputA': {
'data': [
-43.333316802978516, -67.89795684814453, 26.462739944458008,
36.74276351928711, -65.1773910522461, -87.70664978027344,
65.27881622314453, -74.05226135253906, -13.827810287475586,
6.981486797332764, 99.83751678466797, 55.802337646484375,
-75.57196044921875, 11.499507904052734, 17.110109329223633,
95.81167602539062, 57.4474983215332, -57.175872802734375,
27.719053268432617, -18.219209671020508, 52.653099060058594,
-69.99455261230469, 39.8216552734375, -29.986528396606445
],
'descriptor': {'dimensions': [24], 'dataType': 'float32'}
},
'inputB': {
'data': [
-59.749725341796875, -44.81494140625, -87.93879699707031,
1.8843363523483276, 84.89464569091797, 47.553653717041016,
85.64292907714844, 43.02861404418945, -60.25821304321289,
15.60616683959961, 70.60614776611328, -7.454866409301758,
-30.20689582824707, -97.69825744628906, -0.00984330102801323,
-77.67960357666016, 30.196685791015625, -59.19007110595703,
89.3588638305664, 28.6798095703125, -29.72130584716797,
-90.6352310180664, 28.2818546295166, 27.662540435791016
],
'descriptor': {'dimensions': [24], 'dataType': 'float32'}
}
},
'operators': [{
'name': 'add',
'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
'outputs': 'output'
}],
'expectedOutputs': {
'output': {
'data': [
-103.08303833007812, -112.71289825439453, -61.47605895996094,
38.627098083496094, 19.717254638671875, -40.15299606323242,
150.9217529296875, -31.02364730834961, -74.08602142333984,
22.58765411376953, 170.44366455078125, 48.34747314453125,
-105.77885437011719, -86.19874572753906, 17.100265502929688,
18.13207244873047, 87.64418029785156, -116.3659439086914,
117.07791900634766, 10.460599899291992, 22.931793212890625,
-160.62979125976562, 68.10350799560547, -2.3239879608154297
],
'descriptor': {'dimensions': [24], 'dataType': 'float32'}
}
}
}
},
{
'name': 'add float32 2D tensors',
'graph': {
'inputs': {
'inputA': {
'data': [
-43.333316802978516, -67.89795684814453, 26.462739944458008,
36.74276351928711, -65.1773910522461, -87.70664978027344,
65.27881622314453, -74.05226135253906, -13.827810287475586,
6.981486797332764, 99.83751678466797, 55.802337646484375,
-75.57196044921875, 11.499507904052734, 17.110109329223633,
95.81167602539062, 57.4474983215332, -57.175872802734375,
27.719053268432617, -18.219209671020508, 52.653099060058594,
-69.99455261230469, 39.8216552734375, -29.986528396606445
],
'descriptor': {'dimensions': [4, 6], 'dataType': 'float32'}
},
'inputB': {
'data': [
-59.749725341796875, -44.81494140625, -87.93879699707031,
1.8843363523483276, 84.89464569091797, 47.553653717041016,
85.64292907714844, 43.02861404418945, -60.25821304321289,
15.60616683959961, 70.60614776611328, -7.454866409301758,
-30.20689582824707, -97.69825744628906, -0.00984330102801323,
-77.67960357666016, 30.196685791015625, -59.19007110595703,
89.3588638305664, 28.6798095703125, -29.72130584716797,
-90.6352310180664, 28.2818546295166, 27.662540435791016
],
'descriptor': {'dimensions': [4, 6], 'dataType': 'float32'}
}
},
'operators': [{
'name': 'add',
'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
'outputs': 'output'
}],
'expectedOutputs': {
'output': {
'data': [
-103.08303833007812, -112.71289825439453, -61.47605895996094,
38.627098083496094, 19.717254638671875, -40.15299606323242,
150.9217529296875, -31.02364730834961, -74.08602142333984,
22.58765411376953, 170.44366455078125, 48.34747314453125,
-105.77885437011719, -86.19874572753906, 17.100265502929688,
18.13207244873047, 87.64418029785156, -116.3659439086914,
117.07791900634766, 10.460599899291992, 22.931793212890625,
-160.62979125976562, 68.10350799560547, -2.3239879608154297
],
'descriptor': {'dimensions': [4, 6], 'dataType': 'float32'}
}
}
}
},
{
'name': 'add float32 3D tensors',
'graph': {
'inputs': {
'inputA': {
'data': [
-43.333316802978516, -67.89795684814453, 26.462739944458008,
36.74276351928711, -65.1773910522461, -87.70664978027344,
65.27881622314453, -74.05226135253906, -13.827810287475586,
6.981486797332764, 99.83751678466797, 55.802337646484375,
-75.57196044921875, 11.499507904052734, 17.110109329223633,
95.81167602539062, 57.4474983215332, -57.175872802734375,
27.719053268432617, -18.219209671020508, 52.653099060058594,
-69.99455261230469, 39.8216552734375, -29.986528396606445
],
'descriptor': {'dimensions': [2, 3, 4], 'dataType': 'float32'}
},
'inputB': {
'data': [
-59.749725341796875, -44.81494140625, -87.93879699707031,
1.8843363523483276, 84.89464569091797, 47.553653717041016,
85.64292907714844, 43.02861404418945, -60.25821304321289,
15.60616683959961, 70.60614776611328, -7.454866409301758,
-30.20689582824707, -97.69825744628906, -0.00984330102801323,
-77.67960357666016, 30.196685791015625, -59.19007110595703,
89.3588638305664, 28.6798095703125, -29.72130584716797,
-90.6352310180664, 28.2818546295166, 27.662540435791016
],
'descriptor': {'dimensions': [2, 3, 4], 'dataType': 'float32'}
}
},
'operators': [{
'name': 'add',
'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
'outputs': 'output'
}],
'expectedOutputs': {
'output': {
'data': [
-103.08303833007812, -112.71289825439453, -61.47605895996094,
38.627098083496094, 19.717254638671875, -40.15299606323242,
150.9217529296875, -31.02364730834961, -74.08602142333984,
22.58765411376953, 170.44366455078125, 48.34747314453125,
-105.77885437011719, -86.19874572753906, 17.100265502929688,
18.13207244873047, 87.64418029785156, -116.3659439086914,
117.07791900634766, 10.460599899291992, 22.931793212890625,
-160.62979125976562, 68.10350799560547, -2.3239879608154297
],
'descriptor': {'dimensions': [2, 3, 4], 'dataType': 'float32'}
}
}
}
},
{
'name': 'add float32 4D tensors',
'graph': {
'inputs': {
'inputA': {
'data': [
-43.333316802978516, -67.89795684814453, 26.462739944458008,
36.74276351928711, -65.1773910522461, -87.70664978027344,
65.27881622314453, -74.05226135253906, -13.827810287475586,
6.981486797332764, 99.83751678466797, 55.802337646484375,
-75.57196044921875, 11.499507904052734, 17.110109329223633,
95.81167602539062, 57.4474983215332, -57.175872802734375,
27.719053268432617, -18.219209671020508, 52.653099060058594,
-69.99455261230469, 39.8216552734375, -29.986528396606445
],
'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
},
'inputB': {
'data': [
-59.749725341796875, -44.81494140625, -87.93879699707031,
1.8843363523483276, 84.89464569091797, 47.553653717041016,
85.64292907714844, 43.02861404418945, -60.25821304321289,
15.60616683959961, 70.60614776611328, -7.454866409301758,
-30.20689582824707, -97.69825744628906, -0.00984330102801323,
-77.67960357666016, 30.196685791015625, -59.19007110595703,
89.3588638305664, 28.6798095703125, -29.72130584716797,
-90.6352310180664, 28.2818546295166, 27.662540435791016
],
'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
}
},
'operators': [{
'name': 'add',
'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
'outputs': 'output'
}],
'expectedOutputs': {
'output': {
'data': [
-103.08303833007812, -112.71289825439453, -61.47605895996094,
38.627098083496094, 19.717254638671875, -40.15299606323242,
150.9217529296875, -31.02364730834961, -74.08602142333984,
22.58765411376953, 170.44366455078125, 48.34747314453125,
-105.77885437011719, -86.19874572753906, 17.100265502929688,
18.13207244873047, 87.64418029785156, -116.3659439086914,
117.07791900634766, 10.460599899291992, 22.931793212890625,
-160.62979125976562, 68.10350799560547, -2.3239879608154297
],
'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
}
}
}
},
{
'name': 'add float32 5D tensors',
'graph': {
'inputs': {
'inputA': {
'data': [
-43.333316802978516, -67.89795684814453, 26.462739944458008,
36.74276351928711, -65.1773910522461, -87.70664978027344,
65.27881622314453, -74.05226135253906, -13.827810287475586,
6.981486797332764, 99.83751678466797, 55.802337646484375,
-75.57196044921875, 11.499507904052734, 17.110109329223633,
95.81167602539062, 57.4474983215332, -57.175872802734375,
27.719053268432617, -18.219209671020508, 52.653099060058594,
-69.99455261230469, 39.8216552734375, -29.986528396606445
],
'descriptor': {'dimensions': [2, 2, 1, 2, 3], 'dataType': 'float32'}
},
'inputB': {
'data': [
-59.749725341796875, -44.81494140625, -87.93879699707031,
1.8843363523483276, 84.89464569091797, 47.553653717041016,
85.64292907714844, 43.02861404418945, -60.25821304321289,
15.60616683959961, 70.60614776611328, -7.454866409301758,
-30.20689582824707, -97.69825744628906, -0.00984330102801323,
-77.67960357666016, 30.196685791015625, -59.19007110595703,
89.3588638305664, 28.6798095703125, -29.72130584716797,
-90.6352310180664, 28.2818546295166, 27.662540435791016
],
'descriptor': {'dimensions': [2, 2, 1, 2, 3], 'dataType': 'float32'}
}
},
'operators': [{
'name': 'add',
'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
'outputs': 'output'
}],
'expectedOutputs': {
'output': {
'data': [
-103.08303833007812, -112.71289825439453, -61.47605895996094,
38.627098083496094, 19.717254638671875, -40.15299606323242,
150.9217529296875, -31.02364730834961, -74.08602142333984,
22.58765411376953, 170.44366455078125, 48.34747314453125,
-105.77885437011719, -86.19874572753906, 17.100265502929688,
18.13207244873047, 87.64418029785156, -116.3659439086914,
117.07791900634766, 10.460599899291992, 22.931793212890625,
-160.62979125976562, 68.10350799560547, -2.3239879608154297
],
'descriptor': {'dimensions': [2, 2, 1, 2, 3], 'dataType': 'float32'}
}
}
}
},
{
'name': 'add float32 broadcast 1D to 4D',
'graph': {
'inputs': {
'inputA': {
'data': [-59.361572265625],
'descriptor': {'dimensions': [1], 'dataType': 'float32'}
},
'inputB': {
'data': [
-43.333316802978516, -67.89795684814453, 26.462739944458008,
36.74276351928711, -65.1773910522461, -87.70664978027344,
65.27881622314453, -74.05226135253906, -13.827810287475586,
6.981486797332764, 99.83751678466797, 55.802337646484375,
-75.57196044921875, 11.499507904052734, 17.110109329223633,
95.81167602539062, 57.4474983215332, -57.175872802734375,
27.719053268432617, -18.219209671020508, 52.653099060058594,
-69.99455261230469, 39.8216552734375, -29.986528396606445
],
'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
}
},
'operators': [{
'name': 'add',
'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
'outputs': 'output'
}],
'expectedOutputs': {
'output': {
'data': [
-102.69488525390625, -127.25952911376953, -32.898834228515625,
-22.61880874633789, -124.5389633178711, -147.06822204589844,
5.917243957519531, -133.41383361816406, -73.18938446044922,
-52.38008499145508, 40.47594451904297, -3.559234619140625,
-134.93353271484375, -47.862064361572266, -42.25146484375,
36.450103759765625, -1.9140739440917969, -116.53744506835938,
-31.642518997192383, -77.58078002929688, -6.708473205566406,
-129.3561248779297, -19.5399169921875, -89.34809875488281
],
'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
}
}
}
},
{
'name': 'add float32 broadcast 2D to 4D',
'graph': {
'inputs': {
'inputA': {
'data': [
-43.333316802978516, -67.89795684814453, 26.462739944458008,
36.74276351928711, -65.1773910522461, -87.70664978027344,
65.27881622314453, -74.05226135253906, -13.827810287475586,
6.981486797332764, 99.83751678466797, 55.802337646484375,
-75.57196044921875, 11.499507904052734, 17.110109329223633,
95.81167602539062, 57.4474983215332, -57.175872802734375,
27.719053268432617, -18.219209671020508, 52.653099060058594,
-69.99455261230469, 39.8216552734375, -29.986528396606445
],
'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
},
'inputB': {
'data': [
-17.981124877929688, -70.45854187011719, -12.762019157409668,
24.254032135009766, -68.12599182128906, 30.62627410888672
],
'descriptor': {'dimensions': [2, 3], 'dataType': 'float32'}
}
},
'operators': [{
'name': 'add',
'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
'outputs': 'output'
}],
'expectedOutputs': {
'output': {
'data': [
-61.3144416809082, -138.35650634765625, 13.70072078704834,
60.996795654296875, -133.30337524414062, -57.08037567138672,
47.297691345214844, -144.51080322265625, -26.589828491210938,
31.235519409179688, 31.711524963378906, 86.4286117553711,
-93.55308532714844, -58.95903396606445, 4.348090171813965,
120.06570434570312, -10.67849349975586, -26.549598693847656,
9.73792839050293, -88.67774963378906, 39.89107894897461,
-45.74052047729492, -28.304336547851562, 0.6397457122802734
],
'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
}
}
}
},
{
'name': 'add float32 broadcast 3D to 4D',
'graph': {
'inputs': {
'inputA': {
'data': [
-43.333316802978516, -67.89795684814453, 26.462739944458008,
36.74276351928711, -65.1773910522461, -87.70664978027344,
65.27881622314453, -74.05226135253906, -13.827810287475586,
6.981486797332764, 99.83751678466797, 55.802337646484375,
-75.57196044921875, 11.499507904052734, 17.110109329223633,
95.81167602539062, 57.4474983215332, -57.175872802734375,
27.719053268432617, -18.219209671020508, 52.653099060058594,
-69.99455261230469, 39.8216552734375, -29.986528396606445
],
'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
},
'inputB': {
'data': [
-32.34067153930664, 43.12499237060547, 78.6887435913086,
-54.49899673461914
],
'descriptor': {'dimensions': [2, 2, 1], 'dataType': 'float32'}
}
},
'operators': [{
'name': 'add',
'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
'outputs': 'output'
}],
'expectedOutputs': {
'output': {
'data': [
-75.67398834228516, -100.23863220214844, -5.877931594848633,
79.86775207519531, -22.052398681640625, -44.58165740966797,
143.96755981445312, 4.636482238769531, 64.86093139648438,
-47.51750946044922, 45.33852005004883, 1.3033409118652344,
-107.91262817382812, -20.841163635253906, -15.230562210083008,
138.93667602539062, 100.57249450683594, -14.050880432128906,
106.40779876708984, 60.46953582763672, 131.3418426513672,
-124.49354553222656, -14.67734146118164, -84.48552703857422
],
'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
}
}
}
},
{
'name': 'add float32 broadcast 4D to 4D',
'graph': {
'inputs': {
'inputA': {
'data': [-59.361572265625],
'descriptor': {'dimensions': [1, 1, 1, 1], 'dataType': 'float32'}
},
'inputB': {
'data': [
-43.333316802978516, -67.89795684814453, 26.462739944458008,
36.74276351928711, -65.1773910522461, -87.70664978027344,
65.27881622314453, -74.05226135253906, -13.827810287475586,
6.981486797332764, 99.83751678466797, 55.802337646484375,
-75.57196044921875, 11.499507904052734, 17.110109329223633,
95.81167602539062, 57.4474983215332, -57.175872802734375,
27.719053268432617, -18.219209671020508, 52.653099060058594,
-69.99455261230469, 39.8216552734375, -29.986528396606445
],
'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
}
},
'operators': [{
'name': 'add',
'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
'outputs': 'output'
}],
'expectedOutputs': {
'output': {
'data': [
-102.69488525390625, -127.25952911376953, -32.898834228515625,
-22.61880874633789, -124.5389633178711, -147.06822204589844,
5.917243957519531, -133.41383361816406, -73.18938446044922,
-52.38008499145508, 40.47594451904297, -3.559234619140625,
-134.93353271484375, -47.862064361572266, -42.25146484375,
36.450103759765625, -1.9140739440917969, -116.53744506835938,
-31.642518997192383, -77.58078002929688, -6.708473205566406,
-129.3561248779297, -19.5399169921875, -89.34809875488281
],
'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
}
}
}
},
{
'name': 'add float32 large inputs',
'graph': {
'inputs': {
'inputA': {
'data': 89.32998657226562,
'descriptor': {'dimensions': [6000, 6000], 'dataType': 'float32'},
'constant': true
},
'inputB': {
'data': 77.24720764160156,
'descriptor': {'dimensions': [6000, 6000], 'dataType': 'float32'}
}
},
'operators': [{
'name': 'add',
'arguments': [{'a': 'inputA'}, {'b': 'inputB'}],
'outputs': 'output'
}],
'expectedOutputs': {
'output': {
'data': 166.5771942138672,
'descriptor': {'dimensions': [6000, 6000], 'dataType': 'float32'}
}
}
}
},
{
'name': 'add float32 with special character names',
'graph': {
'inputs': {
'12-L#!.☺': {
'data': [89.32998657226562],
'descriptor': {'dimensions': [1], 'dataType': 'float32'},
'constant': true
},
'🤦🏼♂️124DS#!F': {
'data': [77.24720764160156],
'descriptor': {'dimensions': [1], 'dataType': 'float32'}
}
},
'operators': [{
'name': 'add',
'arguments': [{'a': '12-L#!.☺'}, {'b': '🤦🏼♂️124DS#!F'}],
'outputs': 'output'
}],
'expectedOutputs': {
'output': {
'data': [166.5771942138672],
'descriptor': {'dimensions': [1], 'dataType': 'float32'}
}
}
}
}
];
if (navigator.ml) {
addTests.forEach((test) => {
webnn_conformance_test(
buildGraphAndCompute, getAddPrecisionTolerance, test);
});
} else {
test(() => assert_implements(navigator.ml, 'missing navigator.ml'));
}