[Mlir-commits] [mlir] [mlir][math] Fix polynomial `math.asin` approximation (PR #101247)
Rob Suderman
llvmlistbot at llvm.org
Tue Jul 30 14:44:57 PDT 2024
https://github.com/rsuderman created https://github.com/llvm/llvm-project/pull/101247
The polynomial approximation for asin is only good between [-9/16, 9/16]. Values beyond that range must be remapped to achieve good numeric results. This is done by the equation below:
`arcsin(x) = PI/2 - arcsin(sqrt(1.0 - x*x))`
>From 3abb1a3d51c9213d79ea043fea0b832e8f442d3e Mon Sep 17 00:00:00 2001
From: Rob Suderman <rob.suderman at gmail.com>
Date: Tue, 30 Jul 2024 14:40:34 -0700
Subject: [PATCH] [mlir][math] Fix polynomial `math.asin` approximation
The polynomial approximation for asin is only good between [-9/16,
9/16]. Values beyond that range must be remapped to achieve good numeric
results. This is done by the equation below:
`arcsin(x) = PI/2 - arcsin(sqrt(1.0 - x*x))`
---
.../Transforms/PolynomialApproximation.cpp | 37 +++++++++++++++++--
.../math-polynomial-approx.mlir | 4 ++
2 files changed, 38 insertions(+), 3 deletions(-)
diff --git a/mlir/lib/Dialect/Math/Transforms/PolynomialApproximation.cpp b/mlir/lib/Dialect/Math/Transforms/PolynomialApproximation.cpp
index f4fae68da63b3..d6fe22158d002 100644
--- a/mlir/lib/Dialect/Math/Transforms/PolynomialApproximation.cpp
+++ b/mlir/lib/Dialect/Math/Transforms/PolynomialApproximation.cpp
@@ -861,7 +861,34 @@ AsinPolynomialApproximation::matchAndRewrite(math::AsinOp op,
return builder.create<arith::MulFOp>(a, b);
};
- Value s = mul(operand, operand);
+ auto sub = [&](Value a, Value b) -> Value {
+ return builder.create<arith::SubFOp>(a, b);
+ };
+
+ auto abs = [&](Value a) -> Value { return builder.create<math::AbsFOp>(a); };
+
+ auto sqrt = [&](Value a) -> Value { return builder.create<math::SqrtOp>(a); };
+
+ auto scopy = [&](Value a, Value b) -> Value {
+ return builder.create<math::CopySignOp>(a, b);
+ };
+
+ auto sel = [&](Value a, Value b, Value c) -> Value {
+ return builder.create<arith::SelectOp>(a, b, c);
+ };
+
+ Value abso = abs(operand);
+ Value aa = mul(operand, operand);
+ Value opp = sqrt(sub(bcast(floatCst(builder, 1.0, elementType)), aa));
+
+ Value gt =
+ builder.create<arith::CmpFOp>(arith::CmpFPredicate::OGT, aa,
+ bcast(floatCst(builder, 0.5, elementType)));
+
+ Value x = sel(gt, opp, abso);
+
+ // Asin(x) approximation for x = [-9/16, 9/16]:
+ Value s = mul(x, x);
Value q = mul(s, s);
Value r = bcast(floatCst(builder, 5.5579749017470502e-2, elementType));
Value t = bcast(floatCst(builder, -6.2027913464120114e-2, elementType));
@@ -878,8 +905,12 @@ AsinPolynomialApproximation::matchAndRewrite(math::AsinOp op,
t = fma(t, q, bcast(floatCst(builder, 7.4999999991367292e-2, elementType)));
r = fma(r, s, t);
r = fma(r, s, bcast(floatCst(builder, 1.6666666666670193e-1, elementType)));
- t = mul(operand, s);
- r = fma(r, t, operand);
+ t = mul(x, s);
+ r = fma(r, t, x);
+
+ Value rsub = sub(bcast(floatCst(builder, 1.57079632679, elementType)), r);
+ r = sel(gt, rsub, r);
+ r = scopy(r, operand);
rewriter.replaceOp(op, r);
return success();
diff --git a/mlir/test/mlir-cpu-runner/math-polynomial-approx.mlir b/mlir/test/mlir-cpu-runner/math-polynomial-approx.mlir
index 370c5baa0adef..b8861198d596b 100644
--- a/mlir/test/mlir-cpu-runner/math-polynomial-approx.mlir
+++ b/mlir/test/mlir-cpu-runner/math-polynomial-approx.mlir
@@ -493,6 +493,10 @@ func.func @asin() {
%cst3 = arith.constant -0.25 : f32
call @asin_f32(%cst3) : (f32) -> ()
+ // CHECK: -1.1197
+ %cst4 = arith.constant -0.90 : f32
+ call @asin_f32(%cst4) : (f32) -> ()
+
// CHECK: 0.25268, 0.384397, 0.597406
%vec_x = arith.constant dense<[0.25, 0.375, 0.5625]> : vector<3xf32>
call @asin_3xf32(%vec_x) : (vector<3xf32>) -> ()
More information about the Mlir-commits
mailing list