// META: title=test WebNN API gelu 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-gelu-method
// Compute the gaussian error linear unit function (GELU) of the input tensor.
// The calculation follows the expression 0.5 * x * (1 + erf(x / sqrt(2))).
//
// MLOperand gelu(MLOperand input);
const getGeluPrecisionTolerance = (graphResources) => {
const toleranceValueDict = {float32: 18, float16: 18};
const expectedDataType =
getExpectedDataTypeOfSingleOutput(graphResources.expectedOutputs);
return {metricType: 'ULP', value: toleranceValueDict[expectedDataType]};
};
const geluTests = [
{
'name': 'gelu float32 0D scalar',
'graph': {
'inputs': {
'geluInput': {
'data': [-0.044885843992233276],
'descriptor': {'dimensions': [], 'dataType': 'float32'}
}
},
'operators': [{
'name': 'gelu',
'arguments': [{'input': 'geluInput'}],
'outputs': 'geluOutput'
}],
'expectedOutputs': {
'geluOutput': {
'data': [-0.021639423444867134],
'descriptor': {'dimensions': [], 'dataType': 'float32'}
}
}
}
},
{
'name': 'gelu float16 0D scalar',
'graph': {
'inputs': {
'geluInput': {
'data': [-0.044891357421875],
'descriptor': {'dimensions': [], 'dataType': 'float16'}
}
},
'operators': [{
'name': 'gelu',
'arguments': [{'input': 'geluInput'}],
'outputs': 'geluOutput'
}],
'expectedOutputs': {
'geluOutput': {
'data': [-0.021636962890625],
'descriptor': {'dimensions': [], 'dataType': 'float16'}
}
}
}
},
{
'name': 'gelu float32 1D tensor',
'graph': {
'inputs': {
'geluInput': {
'data': [
0.878292441368103, -0.09706497937440872, 0.1367187649011612,
0.46406492590904236, -0.26635801792144775, -0.8252315521240234,
0.8530909419059753, 0.3846154808998108, 0.6772316694259644,
-0.4811072051525116, 0.2983909249305725, 0.6777864098548889,
-0.526228129863739, 0.3497541546821594, -0.12918996810913086,
0.5853934288024902, -0.8950720429420471, 0.028302494436502457,
-0.09901237487792969, -0.8838679790496826, -0.596120297908783,
0.31863871216773987, 0.4794037640094757, -0.06489315629005432
],
'descriptor': {'dimensions': [24], 'dataType': 'float32'}
}
},
'operators': [{
'name': 'gelu',
'arguments': [{'input': 'geluInput'}],
'outputs': 'geluOutput'
}],
'expectedOutputs': {
'geluOutput': {
'data': [
0.7115113139152527, -0.0447796992957592, 0.07579325884580612,
0.3149605691432953, -0.10520657151937485, -0.16885890066623688,
0.6851989030838013, 0.24989959597587585, 0.508513331413269,
-0.1516546905040741, 0.18419598042964935, 0.509049117565155,
-0.15753419697284698, 0.22270187735557556, -0.05795508995652199,
0.42198580503463745, -0.1659233123064041, 0.014470770955085754,
-0.04560155048966408, -0.1665063202381134, -0.1642593890428543,
0.19914908707141876, 0.3279957175254822, -0.030767757445573807
],
'descriptor': {'dimensions': [24], 'dataType': 'float32'}
}
}
}
},
{
'name': 'gelu float32 1D constant tensor',
'graph': {
'inputs': {
'geluInput': {
'data': [
0.878292441368103, -0.09706497937440872, 0.1367187649011612,
0.46406492590904236, -0.26635801792144775, -0.8252315521240234,
0.8530909419059753, 0.3846154808998108, 0.6772316694259644,
-0.4811072051525116, 0.2983909249305725, 0.6777864098548889,
-0.526228129863739, 0.3497541546821594, -0.12918996810913086,
0.5853934288024902, -0.8950720429420471, 0.028302494436502457,
-0.09901237487792969, -0.8838679790496826, -0.596120297908783,
0.31863871216773987, 0.4794037640094757, -0.06489315629005432
],
'descriptor': {'dimensions': [24], 'dataType': 'float32'},
'constant': true
}
},
'operators': [{
'name': 'gelu',
'arguments': [{'input': 'geluInput'}],
'outputs': 'geluOutput'
}],
'expectedOutputs': {
'geluOutput': {
'data': [
0.7115113139152527, -0.0447796992957592, 0.07579325884580612,
0.3149605691432953, -0.10520657151937485, -0.16885890066623688,
0.6851989030838013, 0.24989959597587585, 0.508513331413269,
-0.1516546905040741, 0.18419598042964935, 0.509049117565155,
-0.15753419697284698, 0.22270187735557556, -0.05795508995652199,
0.42198580503463745, -0.1659233123064041, 0.014470770955085754,
-0.04560155048966408, -0.1665063202381134, -0.1642593890428543,
0.19914908707141876, 0.3279957175254822, -0.030767757445573807
],
'descriptor': {'dimensions': [24], 'dataType': 'float32'}
}
}
}
},
{
'name': 'gelu float16 1D tensor',
'graph': {
'inputs': {
'geluInput': {
'data': [
0.87841796875, -0.0970458984375, 0.13671875,
0.464111328125, -0.266357421875, -0.8251953125,
0.85302734375, 0.384521484375, 0.67724609375,
-0.481201171875, 0.29833984375, 0.677734375,
-0.5263671875, 0.349853515625, -0.129150390625,
0.58544921875, -0.89501953125, 0.0283050537109375,
-0.0989990234375, -0.8837890625, -0.59619140625,
0.318603515625, 0.4794921875, -0.06488037109375
],
'descriptor': {'dimensions': [24], 'dataType': 'float16'}
}
},
'operators': [{
'name': 'gelu',
'arguments': [{'input': 'geluInput'}],
'outputs': 'geluOutput'
}],
'expectedOutputs': {
'geluOutput': {
'data': [
0.71142578125, -0.044769287109375, 0.0758056640625,
0.31494140625, -0.105224609375, -0.1688232421875,
0.68505859375, 0.2498779296875, 0.50830078125,
-0.151611328125, 0.1842041015625, 0.5087890625,
-0.1575927734375, 0.2227783203125, -0.057952880859375,
0.422119140625, -0.1658935546875, 0.01447296142578125,
-0.04559326171875, -0.16650390625, -0.164306640625,
0.1990966796875, 0.328125, -0.03076171875
],
'descriptor': {'dimensions': [24], 'dataType': 'float16'}
}
}
}
},
{
'name': 'gelu float32 2D tensor',
'graph': {
'inputs': {
'geluInput': {
'data': [
0.878292441368103, -0.09706497937440872, 0.1367187649011612,
0.46406492590904236, -0.26635801792144775, -0.8252315521240234,
0.8530909419059753, 0.3846154808998108, 0.6772316694259644,
-0.4811072051525116, 0.2983909249305725, 0.6777864098548889,
-0.526228129863739, 0.3497541546821594, -0.12918996810913086,
0.5853934288024902, -0.8950720429420471, 0.028302494436502457,
-0.09901237487792969, -0.8838679790496826, -0.596120297908783,
0.31863871216773987, 0.4794037640094757, -0.06489315629005432
],
'descriptor': {'dimensions': [4, 6], 'dataType': 'float32'}
}
},
'operators': [{
'name': 'gelu',
'arguments': [{'input': 'geluInput'}],
'outputs': 'geluOutput'
}],
'expectedOutputs': {
'geluOutput': {
'data': [
0.7115113139152527, -0.0447796992957592, 0.07579325884580612,
0.3149605691432953, -0.10520657151937485, -0.16885890066623688,
0.6851989030838013, 0.24989959597587585, 0.508513331413269,
-0.1516546905040741, 0.18419598042964935, 0.509049117565155,
-0.15753419697284698, 0.22270187735557556, -0.05795508995652199,
0.42198580503463745, -0.1659233123064041, 0.014470770955085754,
-0.04560155048966408, -0.1665063202381134, -0.1642593890428543,
0.19914908707141876, 0.3279957175254822, -0.030767757445573807
],
'descriptor': {'dimensions': [4, 6], 'dataType': 'float32'}
}
}
}
},
{
'name': 'gelu float16 2D tensor',
'graph': {
'inputs': {
'geluInput': {
'data': [
0.87841796875, -0.0970458984375, 0.13671875,
0.464111328125, -0.266357421875, -0.8251953125,
0.85302734375, 0.384521484375, 0.67724609375,
-0.481201171875, 0.29833984375, 0.677734375,
-0.5263671875, 0.349853515625, -0.129150390625,
0.58544921875, -0.89501953125, 0.0283050537109375,
-0.0989990234375, -0.8837890625, -0.59619140625,
0.318603515625, 0.4794921875, -0.06488037109375
],
'descriptor': {'dimensions': [4, 6], 'dataType': 'float16'}
}
},
'operators': [{
'name': 'gelu',
'arguments': [{'input': 'geluInput'}],
'outputs': 'geluOutput'
}],
'expectedOutputs': {
'geluOutput': {
'data': [
0.71142578125, -0.044769287109375, 0.0758056640625,
0.31494140625, -0.105224609375, -0.1688232421875,
0.68505859375, 0.2498779296875, 0.50830078125,
-0.151611328125, 0.1842041015625, 0.5087890625,
-0.1575927734375, 0.2227783203125, -0.057952880859375,
0.422119140625, -0.1658935546875, 0.01447296142578125,
-0.04559326171875, -0.16650390625, -0.164306640625,
0.1990966796875, 0.328125, -0.03076171875
],
'descriptor': {'dimensions': [4, 6], 'dataType': 'float16'}
}
}
}
},
{
'name': 'gelu float32 3D tensor',
'graph': {
'inputs': {
'geluInput': {
'data': [
0.878292441368103, -0.09706497937440872, 0.1367187649011612,
0.46406492590904236, -0.26635801792144775, -0.8252315521240234,
0.8530909419059753, 0.3846154808998108, 0.6772316694259644,
-0.4811072051525116, 0.2983909249305725, 0.6777864098548889,
-0.526228129863739, 0.3497541546821594, -0.12918996810913086,
0.5853934288024902, -0.8950720429420471, 0.028302494436502457,
-0.09901237487792969, -0.8838679790496826, -0.596120297908783,
0.31863871216773987, 0.4794037640094757, -0.06489315629005432
],
'descriptor': {'dimensions': [2, 3, 4], 'dataType': 'float32'}
}
},
'operators': [{
'name': 'gelu',
'arguments': [{'input': 'geluInput'}],
'outputs': 'geluOutput'
}],
'expectedOutputs': {
'geluOutput': {
'data': [
0.7115113139152527, -0.0447796992957592, 0.07579325884580612,
0.3149605691432953, -0.10520657151937485, -0.16885890066623688,
0.6851989030838013, 0.24989959597587585, 0.508513331413269,
-0.1516546905040741, 0.18419598042964935, 0.509049117565155,
-0.15753419697284698, 0.22270187735557556, -0.05795508995652199,
0.42198580503463745, -0.1659233123064041, 0.014470770955085754,
-0.04560155048966408, -0.1665063202381134, -0.1642593890428543,
0.19914908707141876, 0.3279957175254822, -0.030767757445573807
],
'descriptor': {'dimensions': [2, 3, 4], 'dataType': 'float32'}
}
}
}
},
{
'name': 'gelu float16 3D tensor',
'graph': {
'inputs': {
'geluInput': {
'data': [
0.87841796875, -0.0970458984375, 0.13671875,
0.464111328125, -0.266357421875, -0.8251953125,
0.85302734375, 0.384521484375, 0.67724609375,
-0.481201171875, 0.29833984375, 0.677734375,
-0.5263671875, 0.349853515625, -0.129150390625,
0.58544921875, -0.89501953125, 0.0283050537109375,
-0.0989990234375, -0.8837890625, -0.59619140625,
0.318603515625, 0.4794921875, -0.06488037109375
],
'descriptor': {'dimensions': [2, 3, 4], 'dataType': 'float16'}
}
},
'operators': [{
'name': 'gelu',
'arguments': [{'input': 'geluInput'}],
'outputs': 'geluOutput'
}],
'expectedOutputs': {
'geluOutput': {
'data': [
0.71142578125, -0.044769287109375, 0.0758056640625,
0.31494140625, -0.105224609375, -0.1688232421875,
0.68505859375, 0.2498779296875, 0.50830078125,
-0.151611328125, 0.1842041015625, 0.5087890625,
-0.1575927734375, 0.2227783203125, -0.057952880859375,
0.422119140625, -0.1658935546875, 0.01447296142578125,
-0.04559326171875, -0.16650390625, -0.164306640625,
0.1990966796875, 0.328125, -0.03076171875
],
'descriptor': {'dimensions': [2, 3, 4], 'dataType': 'float16'}
}
}
}
},
{
'name': 'gelu float32 4D tensor',
'graph': {
'inputs': {
'geluInput': {
'data': [
0.878292441368103, -0.09706497937440872, 0.1367187649011612,
0.46406492590904236, -0.26635801792144775, -0.8252315521240234,
0.8530909419059753, 0.3846154808998108, 0.6772316694259644,
-0.4811072051525116, 0.2983909249305725, 0.6777864098548889,
-0.526228129863739, 0.3497541546821594, -0.12918996810913086,
0.5853934288024902, -0.8950720429420471, 0.028302494436502457,
-0.09901237487792969, -0.8838679790496826, -0.596120297908783,
0.31863871216773987, 0.4794037640094757, -0.06489315629005432
],
'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
}
},
'operators': [{
'name': 'gelu',
'arguments': [{'input': 'geluInput'}],
'outputs': 'geluOutput'
}],
'expectedOutputs': {
'geluOutput': {
'data': [
0.7115113139152527, -0.0447796992957592, 0.07579325884580612,
0.3149605691432953, -0.10520657151937485, -0.16885890066623688,
0.6851989030838013, 0.24989959597587585, 0.508513331413269,
-0.1516546905040741, 0.18419598042964935, 0.509049117565155,
-0.15753419697284698, 0.22270187735557556, -0.05795508995652199,
0.42198580503463745, -0.1659233123064041, 0.014470770955085754,
-0.04560155048966408, -0.1665063202381134, -0.1642593890428543,
0.19914908707141876, 0.3279957175254822, -0.030767757445573807
],
'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
}
}
}
},
{
'name': 'gelu float16 4D tensor',
'graph': {
'inputs': {
'geluInput': {
'data': [
0.87841796875, -0.0970458984375, 0.13671875,
0.464111328125, -0.266357421875, -0.8251953125,
0.85302734375, 0.384521484375, 0.67724609375,
-0.481201171875, 0.29833984375, 0.677734375,
-0.5263671875, 0.349853515625, -0.129150390625,
0.58544921875, -0.89501953125, 0.0283050537109375,
-0.0989990234375, -0.8837890625, -0.59619140625,
0.318603515625, 0.4794921875, -0.06488037109375
],
'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float16'}
}
},
'operators': [{
'name': 'gelu',
'arguments': [{'input': 'geluInput'}],
'outputs': 'geluOutput'
}],
'expectedOutputs': {
'geluOutput': {
'data': [
0.71142578125, -0.044769287109375, 0.0758056640625,
0.31494140625, -0.105224609375, -0.1688232421875,
0.68505859375, 0.2498779296875, 0.50830078125,
-0.151611328125, 0.1842041015625, 0.5087890625,
-0.1575927734375, 0.2227783203125, -0.057952880859375,
0.422119140625, -0.1658935546875, 0.01447296142578125,
-0.04559326171875, -0.16650390625, -0.164306640625,
0.1990966796875, 0.328125, -0.03076171875
],
'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float16'}
}
}
}
},
{
'name': 'gelu float32 5D tensor',
'graph': {
'inputs': {
'geluInput': {
'data': [
0.878292441368103, -0.09706497937440872, 0.1367187649011612,
0.46406492590904236, -0.26635801792144775, -0.8252315521240234,
0.8530909419059753, 0.3846154808998108, 0.6772316694259644,
-0.4811072051525116, 0.2983909249305725, 0.6777864098548889,
-0.526228129863739, 0.3497541546821594, -0.12918996810913086,
0.5853934288024902, -0.8950720429420471, 0.028302494436502457,
-0.09901237487792969, -0.8838679790496826, -0.596120297908783,
0.31863871216773987, 0.4794037640094757, -0.06489315629005432
],
'descriptor': {'dimensions': [2, 1, 4, 1, 3], 'dataType': 'float32'}
}
},
'operators': [{
'name': 'gelu',
'arguments': [{'input': 'geluInput'}],
'outputs': 'geluOutput'
}],
'expectedOutputs': {
'geluOutput': {
'data': [
0.7115113139152527, -0.0447796992957592, 0.07579325884580612,
0.3149605691432953, -0.10520657151937485, -0.16885890066623688,
0.6851989030838013, 0.24989959597587585, 0.508513331413269,
-0.1516546905040741, 0.18419598042964935, 0.509049117565155,
-0.15753419697284698, 0.22270187735557556, -0.05795508995652199,
0.42198580503463745, -0.1659233123064041, 0.014470770955085754,
-0.04560155048966408, -0.1665063202381134, -0.1642593890428543,
0.19914908707141876, 0.3279957175254822, -0.030767757445573807
],
'descriptor': {'dimensions': [2, 1, 4, 1, 3], 'dataType': 'float32'}
}
}
}
},
{
'name': 'gelu float16 5D tensor',
'graph': {
'inputs': {
'geluInput': {
'data': [
0.87841796875, -0.0970458984375, 0.13671875,
0.464111328125, -0.266357421875, -0.8251953125,
0.85302734375, 0.384521484375, 0.67724609375,
-0.481201171875, 0.29833984375, 0.677734375,
-0.5263671875, 0.349853515625, -0.129150390625,
0.58544921875, -0.89501953125, 0.0283050537109375,
-0.0989990234375, -0.8837890625, -0.59619140625,
0.318603515625, 0.4794921875, -0.06488037109375
],
'descriptor': {'dimensions': [2, 1, 4, 1, 3], 'dataType': 'float16'}
}
},
'operators': [{
'name': 'gelu',
'arguments': [{'input': 'geluInput'}],
'outputs': 'geluOutput'
}],
'expectedOutputs': {
'geluOutput': {
'data': [
0.71142578125, -0.044769287109375, 0.0758056640625,
0.31494140625, -0.105224609375, -0.1688232421875,
0.68505859375, 0.2498779296875, 0.50830078125,
-0.151611328125, 0.1842041015625, 0.5087890625,
-0.1575927734375, 0.2227783203125, -0.057952880859375,
0.422119140625, -0.1658935546875, 0.01447296142578125,
-0.04559326171875, -0.16650390625, -0.164306640625,
0.1990966796875, 0.328125, -0.03076171875
],
'descriptor': {'dimensions': [2, 1, 4, 1, 3], 'dataType': 'float16'}
}
}
}
}
];
if (navigator.ml) {
geluTests.forEach((test) => {
webnn_conformance_test(
buildGraphAndCompute, getGeluPrecisionTolerance, test);
});
} else {
test(() => assert_implements(navigator.ml, 'missing navigator.ml'));
}