From 4055abbc290c41bd31932e422862add7bf564eac Mon Sep 17 00:00:00 2001 From: Joshua Bell Date: Thu, 9 May 2024 11:46:29 -0700 Subject: [PATCH 1/3] Validate axes and input rank for reduction ops Suggested behavior matches the Chromium prototype implementation. Fixes #681 --- index.bs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/index.bs b/index.bs index ff549041..ef6f7dde 100644 --- a/index.bs +++ b/index.bs @@ -1438,7 +1438,7 @@ partial interface MLGraphBuilder { 1. [=Assert=]: |op| is one of "argMin", "argMax". 1. If [=MLGraphBuilder/validating operand=] with [=this=] and |input| returns false, then [=exception/throw=] a {{TypeError}}. 1. If |options|.{{MLArgMinMaxOptions/axes}} [=map/exists=], if any of its elements is not in [=the range=] 0 to |input|'s [=MLOperand/rank=], exclusive, then [=exception/throw=] a {{TypeError}}. - 1. Let |outputShape| be the result of [=MLGraphBuilder/calculating reduction output sizes=] given |input|'s [=MLOperand/shape=], |options|.{{MLArgMinMaxOptions/axes}} (if it [=map/exists=]), and |options|.{{MLArgMinMaxOptions/keepDimensions}}. + 1. Let |outputShape| be the result of [=MLGraphBuilder/calculating reduction output sizes=] given |input|'s [=MLOperand/shape=], |options|.{{MLArgMinMaxOptions/axes}} (if it [=map/exists=]), and |options|.{{MLArgMinMaxOptions/keepDimensions}}. If that returns failure, then [=exception/throw=] a {{TypeError}}. 1. Let |desc| be a new {{MLOperandDescriptor}}. 1. Set |desc|.{{MLOperandDescriptor/dataType}} to {{MLOperandDataType/"int64"}}. 1. Set |desc|.{{MLOperandDescriptor/dimensions}} to |outputShape|. @@ -4841,10 +4841,12 @@ partial interface MLGraphBuilder {
- To calculate reduction output sizes, given a [=/list=] of unsigned integers |inputShape|, a optional [=/list=] of unsigned integers |axes|, and [=/boolean=] |keepDimensions|, perform the following steps. They return a new [=/list=] of unsigned integers. + To calculate reduction output sizes, given a [=/list=] of unsigned integers |inputShape|, a optional [=/list=] of unsigned integers |axes|, and [=/boolean=] |keepDimensions|, perform the following steps. They return a new [=/list=] of unsigned integers, or failure. 1. Let |inputRank| be |inputShape|'s [=list/size=]. + 1. If |inputRank| is 0, then return failure. 1. If |axes| is not given, let |axes| be [=the range=] 0 to |inputRank|, exclusive. + 1. Otherwise, if |axes| contains duplicate values, then return failure. 1. If |keepDimensions| is true, then: 1. Let |outputShape| be a [=list/clone=] of |inputShape|. 1. [=list/For each=] |axis| of |axes|: @@ -4864,7 +4866,7 @@ partial interface MLGraphBuilder { 1. If [=MLGraphBuilder/validating operand=] with [=this=] and |input| returns false, then [=exception/throw=] a {{TypeError}}. 1. If |allowedDataTypes| is given and it does not [=list/contain=] |input|'s [=MLOperand/dataType=], then [=exception/throw=] a {{TypeError}}. 1. If |options|.{{MLReduceOptions/axes}} [=map/exists=], if any of its elements is not in [=the range=] 0 to |input|'s [=MLOperand/rank=], exclusive, then [=exception/throw=] a {{TypeError}}. - 1. Let |outputShape| be the result of [=MLGraphBuilder/calculating reduction output sizes=] given |input|'s [=MLOperand/shape=], |options|.{{MLReduceOptions/axes}} (if it [=map/exists=]), and |options|.{{MLReduceOptions/keepDimensions}}. + 1. Let |outputShape| be the result of [=MLGraphBuilder/calculating reduction output sizes=] given |input|'s [=MLOperand/shape=], |options|.{{MLReduceOptions/axes}} (if it [=map/exists=]), and |options|.{{MLReduceOptions/keepDimensions}}. If that returns failure, then [=exception/throw=] a {{TypeError}}. 1. Let |desc| be a new {{MLOperandDescriptor}}. 1. Set |desc|.{{MLOperandDescriptor/dataType}} to |input|'s [=MLOperand/dataType=]. 1. Set |desc|.{{MLOperandDescriptor/dimensions}} to |outputShape|. From b998e04f5d56c1fce918950347fc2945fe5e379c Mon Sep 17 00:00:00 2001 From: Joshua Bell Date: Fri, 10 May 2024 08:58:26 -0700 Subject: [PATCH 2/3] Remove inputRank != 0 restriction Nop reductions are valid (where axes are empty) Co-authored-by: Dwayne Robinson --- index.bs | 1 - 1 file changed, 1 deletion(-) diff --git a/index.bs b/index.bs index ef6f7dde..4643558e 100644 --- a/index.bs +++ b/index.bs @@ -4844,7 +4844,6 @@ partial interface MLGraphBuilder { To calculate reduction output sizes, given a [=/list=] of unsigned integers |inputShape|, a optional [=/list=] of unsigned integers |axes|, and [=/boolean=] |keepDimensions|, perform the following steps. They return a new [=/list=] of unsigned integers, or failure. 1. Let |inputRank| be |inputShape|'s [=list/size=]. - 1. If |inputRank| is 0, then return failure. 1. If |axes| is not given, let |axes| be [=the range=] 0 to |inputRank|, exclusive. 1. Otherwise, if |axes| contains duplicate values, then return failure. 1. If |keepDimensions| is true, then: From 057019c1d5fa1789a291150036400ca45b56eed8 Mon Sep 17 00:00:00 2001 From: Joshua Bell Date: Mon, 13 May 2024 09:22:19 -0700 Subject: [PATCH 3/3] Move axes vs. rank validation into helper algorithm --- index.bs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/index.bs b/index.bs index 92350d9f..328ff1b4 100644 --- a/index.bs +++ b/index.bs @@ -1437,7 +1437,6 @@ partial interface MLGraphBuilder { 1. [=Assert=]: |op| is one of "argMin", "argMax". 1. If [=MLGraphBuilder/validating operand=] with [=this=] and |input| returns false, then [=exception/throw=] a {{TypeError}}. - 1. If |options|.{{MLArgMinMaxOptions/axes}} [=map/exists=], if any of its elements is not in [=the range=] 0 to |input|'s [=MLOperand/rank=], exclusive, then [=exception/throw=] a {{TypeError}}. 1. Let |outputShape| be the result of [=MLGraphBuilder/calculating reduction output sizes=] given |input|'s [=MLOperand/shape=], |options|.{{MLArgMinMaxOptions/axes}} (if it [=map/exists=]), and |options|.{{MLArgMinMaxOptions/keepDimensions}}. If that returns failure, then [=exception/throw=] a {{TypeError}}. 1. Let |desc| be a new {{MLOperandDescriptor}}. 1. Set |desc|.{{MLOperandDescriptor/dataType}} to {{MLOperandDataType/"int64"}}. @@ -4842,7 +4841,7 @@ partial interface MLGraphBuilder { 1. Let |inputRank| be |inputShape|'s [=list/size=]. 1. If |axes| is not given, let |axes| be [=the range=] 0 to |inputRank|, exclusive. - 1. Otherwise, if |axes| contains duplicate values, then return failure. + 1. Otherwise, if |axes| contains duplicate values, or if any of its elements is not in [=the range=] 0 to |inputRank|, exclusive, then return failure. 1. If |keepDimensions| is true, then: 1. Let |outputShape| be a [=list/clone=] of |inputShape|. 1. [=list/For each=] |axis| of |axes|: @@ -4861,7 +4860,6 @@ partial interface MLGraphBuilder { 1. [=Assert=]: |op| is one of "reduceL1", "reduceL2", "reduceLogSum", "reduceLogSumExp", "reduceMax", "reduceMean", "reduceMin", "reduceProduct", "reduceSum", "reduceSumSquare". 1. If [=MLGraphBuilder/validating operand=] with [=this=] and |input| returns false, then [=exception/throw=] a {{TypeError}}. 1. If |allowedDataTypes| is given and it does not [=list/contain=] |input|'s [=MLOperand/dataType=], then [=exception/throw=] a {{TypeError}}. - 1. If |options|.{{MLReduceOptions/axes}} [=map/exists=], if any of its elements is not in [=the range=] 0 to |input|'s [=MLOperand/rank=], exclusive, then [=exception/throw=] a {{TypeError}}. 1. Let |outputShape| be the result of [=MLGraphBuilder/calculating reduction output sizes=] given |input|'s [=MLOperand/shape=], |options|.{{MLReduceOptions/axes}} (if it [=map/exists=]), and |options|.{{MLReduceOptions/keepDimensions}}. If that returns failure, then [=exception/throw=] a {{TypeError}}. 1. Let |desc| be a new {{MLOperandDescriptor}}. 1. Set |desc|.{{MLOperandDescriptor/dataType}} to |input|'s [=MLOperand/dataType=].