From f83ecfddd414f5ad912eb3d9916476d58401a5e2 Mon Sep 17 00:00:00 2001 From: Joshua Bell Date: Tue, 9 Apr 2024 13:07:43 -0700 Subject: [PATCH 01/17] Introduce MLNumber for specifying numeric inputs of any type For some MLGraphBuilder methods the type of a numeric input can vary - e.g. for constant() an explicit MLOperandDataType is provided; for clamp() and pad() the data type is implied by input operands. In these cases, specifying the numeric value as either a float/double or int64 type runs into accuracy or range issues - you can't accurately represent all int64 values as a double, and you can't represent the full range of floats as int64. (You also can't represent all int64 values as an long long either - over 2^53 things get wierd. But that's a digression.) Per discussion in https://github.com/whatwg/webidl/issues/1388 this change introduces a union between a bigint type and unrestricted double called MLNumber. Callers can pass a JS number (1234, 1.1234e38) or a JS bigint (9007199254740993n), and the implementation will treat it properly based on the explicit or implicit MLOperandDataType. Usage of this type should be limited to only those cases. Fixes #442 Note that #492 proposes changes to the constant sequential filling operation; this just adds IDL to match the current spec prose. Some of the concerns raised in #325 are addressed (e.g. clamp()'s options). However, several other options are still specified as "float", and should maybe be "double" - but MLNumber is likely not appropriate for those, so they are not updated here. --- index.bs | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/index.bs b/index.bs index 3b07c538..0d3dbbf9 100644 --- a/index.bs +++ b/index.bs @@ -1074,6 +1074,8 @@ interface MLOperand { MLOperandDataType dataType(); sequence shape(); }; + +typedef (bigint or unrestricted double) MLNumber;
@@ -1133,6 +1135,16 @@ The {{MLOperand}} objects are created by the methods of {{MLGraphBuilder}}, inte To validate operand given {{MLGraphBuilder}} |builder| and {{MLOperand}} |operand|, return true if |operand|.{{MLOperand/[[builder]]}} is |builder|, and false otherwise.

+#### {{MLNumber}} #### {#api-mlnumber-typedef} + +MLNumber is used when specifying the type of a numeric option for an {{MLOperand}} which can be of any {{MLOperandDataType}}, including both 64-bit integer types ({{MLOperandDataType/"uint64"}} and {{MLOperandDataType/"int64"}}) and 32-bit floating point ({{MLOperandDataType/"float32"}}). Implementations must process the value according to the corresponding {{MLOperandDataType}}. + +
+ Specifying the option as {{double}} would lose accuracy when passing values over 253, and specifying {{long long}} would disallow values over 263. +
+ +Issue(whatwg/webidl#1388): Support for unions of {{bigint}} and [=numeric types=] new in [[WebIDL]], and implementation support is also limited. Prototype implementations are encouraged to provide feedback for this approach. + ### {{MLOperand/dataType()}} ### {#api-mloperand-datatype} Return a data type of the {{MLOperand}}. @@ -1229,7 +1241,13 @@ interface MLGraphBuilder { MLOperand constant(MLOperandDescriptor descriptor, ArrayBufferView bufferView); // Create a single-value operand from the specified number of the specified type. - MLOperand constant(double value, optional MLOperandDataType type = "float32"); + MLOperand constant(MLNumber value, optional MLOperandDataType type = "float32"); + + // Create an operand for a constant 1-D tensor of the specified type and range. + MLOperand constant(MLNumber start, + MLNumber end, + MLNumber step, + optional MLOperandDataType type = "float32"); // Compile the graph up to the specified output operands asynchronously. Promise build(MLNamedOperands outputs); @@ -1322,7 +1340,7 @@ Data truncation will occur when the specified value exceeds the range of the spe
**Arguments:** - - *value*: a {{float}} number. The value of the constant. + - *value*: an {{MLNumber}}. The value of the constant. - *type*: an optional {{MLOperandDataType}}. If not specified, it is assumed to be {{MLOperandDataType/"float32"}}. **Returns:** an {{MLOperand}}. The constant output.
@@ -1349,9 +1367,9 @@ Data truncation will occur when the values in the range exceed the range of the
**Arguments:** - - *start*: a {{float}} scalar. The starting value of the range. - - *end*: a {{float}} scalar. The ending value of the range. - - *step*: a {{float}} scalar. The gap value between two data points in the range. + - *start*: an {{MLNumber}}. The starting value of the range. + - *end*: an {{MLNumber}}. The ending value of the range. + - *step*: an {{MLNumber}}. The gap value between two data points in the range. - *type*: an optional {{MLOperandDataType}}. If not specified, it is assumed to be {{MLOperandDataType/"float32"}}. **Returns:** an {{MLOperand}}. The constant 1-D output tensor of size `max(0, ceil((end - start)/step))`.
@@ -1633,8 +1651,8 @@ partial interface MLGraphBuilder { Clamp the input tensor element-wise within a range specified by the minimum and maximum values.
@@ -1145,6 +1146,8 @@ When used with an {{MLActivation}}, the data type is not known until the activat Specifying the option as {{double}} would lose accuracy when passing values over 253, and specifying {{long long}} would disallow values over 263.
+MLFiniteNumber is the same as {{MLNumber}} except it excludes Infinity, -Infinity, and NaN values. + Issue(whatwg/webidl#1388): Support for unions of {{bigint}} and [=numeric types=] new in [[WEBIDL]], and implementation support is also limited. Prototype implementations are encouraged to provide feedback for this approach. ### {{MLOperand/dataType()}} ### {#api-mloperand-datatype} @@ -4429,7 +4432,7 @@ enum MLPaddingMode { dictionary MLPadOptions { MLPaddingMode mode = "constant"; - MLNumber value = 0; + MLFiniteNumber value = 0; }; partial interface MLGraphBuilder { From 9f0dd89610562177056064fa9fde8bf3edf3230d Mon Sep 17 00:00:00 2001 From: Joshua Bell Date: Wed, 8 May 2024 16:00:53 -0700 Subject: [PATCH 06/17] WIP for https://github.com/webmachinelearning/webnn/issues/678 - Introduce a "cast" definition that takes a number and a type, and returns the number cast to that type. - Invoke cast during MLOperand and MLActivation creation. TODO: - Passing restrictions - Floating point - allow Infinities/NaNs or not? - Integer - throw or clamp if out of range? - Simplify supported restrictions - resample2d sizes option - is this part of the op data or not? --- index.bs | 143 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 138 insertions(+), 5 deletions(-) diff --git a/index.bs b/index.bs index 72dc0fc8..feced020 100644 --- a/index.bs +++ b/index.bs @@ -44,6 +44,7 @@ urlPrefix: https://tc39.es/ecma262/; spec: ECMA-262 text: element size; url: table-the-typedarray-constructors text: element type; url: table-the-typedarray-constructors text: view constructor; url: table-the-typedarray-constructors + text: equally close values; url: sec-ecmascript-language-types-number-type