79 lines
2.0 KiB
Plaintext
79 lines
2.0 KiB
Plaintext
// polynomial for approximating single precision tan(x)
|
|
//
|
|
// Copyright (c) 2022-2023, Arm Limited.
|
|
// SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
|
|
|
|
dtype = single;
|
|
|
|
mthd = 0; // approximate tan
|
|
deg = 5; // poly degree
|
|
|
|
// // Uncomment for cotan
|
|
// mthd = 1; // approximate cotan
|
|
// deg = 3; // poly degree
|
|
|
|
// interval bounds
|
|
a = 0x1.0p-126;
|
|
b = pi / 4;
|
|
|
|
print("Print some useful constants");
|
|
display = hexadecimal!;
|
|
if (dtype==double) then { prec = 53!; }
|
|
else if (dtype==single) then { prec = 23!; };
|
|
|
|
print("pi/4");
|
|
pi/4;
|
|
|
|
// Setup precisions (display and computation)
|
|
display = decimal!;
|
|
prec=128!;
|
|
save_prec=prec;
|
|
|
|
//
|
|
// Select function to approximate with Sollya
|
|
//
|
|
if(mthd==0) then {
|
|
s = "x + x^3 * P(x^2)";
|
|
g = tan(x);
|
|
F = proc(P) { return x + x^3 * P(x^2); };
|
|
f = (g(sqrt(x))-sqrt(x))/(x*sqrt(x));
|
|
init_poly = 0;
|
|
// Display info
|
|
print("Approximate g(x) =", g, "as F(x)=", s, ".");
|
|
poly = fpminimax(f, deg, [|dtype ...|], [a*a;b*b]);
|
|
}
|
|
else if (mthd==1) then {
|
|
s = "1/x + x * P(x^2)";
|
|
g = 1 / tan(x);
|
|
F = proc(P) { return 1/x + x * P(x^2); };
|
|
f = (g(sqrt(x))-1/sqrt(x))/(sqrt(x));
|
|
init_poly = 0;
|
|
deg_init_poly = -1; // a value such that we actually start by building constant coefficient
|
|
// Display info
|
|
print("Approximate g(x) =", g, "as F(x)=", s, ".");
|
|
// Fpminimax used to minimise absolute error
|
|
approx_fpminimax = proc(func, poly, d) {
|
|
return fpminimax(func - poly / x^-(deg-d), 0, [|dtype|], [a;b], absolute, floating);
|
|
};
|
|
// Optimise all coefficients at once
|
|
poly = fpminimax(f, [|0,...,deg|], [|dtype ...|], [a;b], absolute, floating);
|
|
};
|
|
|
|
|
|
//
|
|
// Display coefficients in Sollya
|
|
//
|
|
display = hexadecimal!;
|
|
if (dtype==double) then { prec = 53!; }
|
|
else if (dtype==single) then { prec = 23!; };
|
|
print("_coeffs :_ hex");
|
|
for i from 0 to deg do coeff(poly, i);
|
|
|
|
// Compute errors
|
|
display = hexadecimal!;
|
|
d_rel_err = dirtyinfnorm(1-F(poly)/g(x), [a;b]);
|
|
d_abs_err = dirtyinfnorm(g(x)-F(poly), [a;b]);
|
|
print("dirty rel error:", d_rel_err);
|
|
print("dirty abs error:", d_abs_err);
|
|
print("in [",a,b,"]");
|