REQUIRE_TRUE(labels->isSameShape(predictions),0,"HUBER_LOSS OP: labels and predictions arrays must have the same shapes, but got %s and %s correspondingly !",ShapeUtils::shapeAsString(labels).c_str(),ShapeUtils::shapeAsString(predictions).c_str());
// weights array can be single scalar or has the same rank as labels, and must be broadcastable to labels
REQUIRE_TRUE(weights->isScalar()||weights->rankOf()==labels->rankOf(),0,"HUBER_LOSS OP: weights array should be scalar or have the same rank as labels array, but got %i and %i correspondingly!",weights->rankOf(),labels->rankOf());
// check whether broadcast operation is possible for weights array
REQUIRE_TRUE(weights->isScalar()||ShapeUtils::areShapesBroadcastable(*weights,*labels),0,"HUBER_LOSS OP: shapes of weights and labels arrays should be broadcastable, but got weights = %s and labels = %s instead!",ShapeUtils::shapeAsString(weights).c_str(),ShapeUtils::shapeAsString(labels).c_str());
// only 4 possible reduction modes exist
REQUIRE_TRUE(reductionMode==0||reductionMode==1||reductionMode==2||reductionMode==3,0,"HUBER_LOSS OP: reduction mode value is not acceptable, possible values are 0, 1, 2, 3, but got %i instead!",reductionMode);
case3:{// 3 - "weighted_sum_by_nonzero_weights", output is scalar and equal to scalar sum of all elements of E array divided by number of non-zero weights
// labels and predictions must have the same shapes
REQUIRE_TRUE(shape::shapeEquals(labelsShapeInfo,predictionsShapeInfo),0,"HUBER_LOSS OP: labels and predictions arrays must have the same shapes, but got %s and %s correspondingly !",ShapeUtils::shapeAsString(labelsShapeInfo).c_str(),ShapeUtils::shapeAsString(predictionsShapeInfo).c_str());
// weights array can be single scalar or has the same rank as labels, and must be broadcastable to labels
REQUIRE_TRUE(shape::isScalar(weightsShapeInfo)||shape::rank(weightsShapeInfo)==shape::rank(labelsShapeInfo),0,"HUBER_LOSS OP: weights array should be scalar or have the same rank as labels array, but got %i and %i correspondingly!",shape::rank(weightsShapeInfo),shape::rank(labelsShapeInfo));
// check whether broadcast operation is possible for weights array
REQUIRE_TRUE(shape::isScalar(weightsShapeInfo)||ShapeUtils::areShapesBroadcastable(weightsShapeInfo,labelsShapeInfo),0,"HUBER_LOSS OP: shapes of weights and labels arrays should be broadcastable, but got weights = %s and labels = %s instead!",ShapeUtils::shapeAsString(weightsShapeInfo).c_str(),ShapeUtils::shapeAsString(labelsShapeInfo).c_str());
// take into account Alex's proposition to treat "none" the same as "weighted_sum" mode when calculating gradients
if(reductionMode==0)
reductionMode=1;
// inputs validation
REQUIRE_TRUE(labels->isSameShape(predictions),0,"HUBER_LOSS_GRAD OP: labels and predictions arrays must have the same shapes, but got %s and %s correspondingly !",ShapeUtils::shapeAsString(labels).c_str(),ShapeUtils::shapeAsString(predictions).c_str());
// weights array can be single scalar or has the same rank as labels, and must be broadcastable to labels
REQUIRE_TRUE(weights->isScalar()||weights->rankOf()==labels->rankOf(),0,"HUBER_LOSS_GRAD OP: weights array should be scalar or have the same rank as labels array, but got %i and %i correspondingly!",weights->rankOf(),labels->rankOf());
// check whether broadcast operation is possible for weights array
REQUIRE_TRUE(weights->isScalar()||ShapeUtils::areShapesBroadcastable(*weights,*labels),0,"HUBER_LOSS_GRAD OP: shapes of weights and labels arrays should be broadcastable, but got weights = %s and labels = %s instead!",ShapeUtils::shapeAsString(weights).c_str(),ShapeUtils::shapeAsString(labels).c_str());
// only 4 possible reduction modes exist
REQUIRE_TRUE(reductionMode==0||reductionMode==1||reductionMode==2||reductionMode==3,0,"HUBER_LOSS_GRAD OP: reduction mode value is not acceptable, possible values are 0, 1, 2, 3, but got %i instead!",reductionMode);
// perform weights broadcasting/tile to labels if needed
case3:{// 3 - "weighted_sum_by_nonzero_weights", output is scalar and equal to scalar sum of all elements of E array divided by number of non-zero weights
// labels and predictions must have the same shapes
REQUIRE_TRUE(shape::shapeEquals(labelsShapeInfo,predictionsShapeInfo),0,"HUBER_LOSS_GRAD OP: labels and predictions arrays must have the same shapes, but got %s and %s correspondingly !",ShapeUtils::shapeAsString(labelsShapeInfo).c_str(),ShapeUtils::shapeAsString(predictionsShapeInfo).c_str());
// weights array can be single scalar or has the same rank as labels, and must be broadcastable to labels
REQUIRE_TRUE(shape::isScalar(weightsShapeInfo)||shape::rank(weightsShapeInfo)==shape::rank(labelsShapeInfo),0,"HUBER_LOSS_GRAD OP: weights array should be scalar or have the same rank as labels array, but got %i and %i correspondingly!",shape::rank(weightsShapeInfo),shape::rank(labelsShapeInfo));
// check whether broadcast operation is possible for weights array
REQUIRE_TRUE(shape::isScalar(weightsShapeInfo)||ShapeUtils::areShapesBroadcastable(weightsShapeInfo,labelsShapeInfo),0,"HUBER_LOSS_GRAD OP: shapes of weights and labels arrays should be broadcastable, but got weights = %s and labels = %s instead!",ShapeUtils::shapeAsString(weightsShapeInfo).c_str(),ShapeUtils::shapeAsString(labelsShapeInfo).c_str());