xref: /freebsd/contrib/arm-optimized-routines/pl/math/tools/exp10.sollya (revision 5ca8e32633c4ffbbcd6762e5888b6a4ba0708c6c)
1// polynomial for approximating 10^x
2//
3// Copyright (c) 2023, Arm Limited.
4// SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
5
6// exp10f parameters
7deg = 5; // poly degree
8N = 1; // Neon 1, SVE 64
9b = log(2)/(2 * N * log(10)); // interval
10a = -b;
11wp = single;
12
13// exp10 parameters
14//deg = 4; // poly degree - bump to 5 for ~1 ULP
15//N = 128; // table size
16//b = log(2)/(2 * N * log(10)); // interval
17//a = -b;
18//wp = D;
19
20
21// find polynomial with minimal relative error
22
23f = 10^x;
24
25// return p that minimizes |f(x) - poly(x) - x^d*p(x)|/|f(x)|
26approx = proc(poly,d) {
27  return remez(1 - poly(x)/f(x), deg-d, [a;b], x^d/f(x), 1e-10);
28};
29// return p that minimizes |f(x) - poly(x) - x^d*p(x)|
30approx_abs = proc(poly,d) {
31  return remez(f(x) - poly(x), deg-d, [a;b], x^d, 1e-10);
32};
33
34// first coeff is fixed, iteratively find optimal double prec coeffs
35poly = 1;
36for i from 1 to deg do {
37  p = roundcoefficients(approx(poly,i), [|wp ...|]);
38//  p = roundcoefficients(approx_abs(poly,i), [|wp ...|]);
39  poly = poly + x^i*coeff(p,0);
40};
41
42display = hexadecimal;
43print("rel error:", accurateinfnorm(1-poly(x)/10^x, [a;b], 30));
44print("abs error:", accurateinfnorm(10^x-poly(x), [a;b], 30));
45print("in [",a,b,"]");
46print("coeffs:");
47for i from 0 to deg do coeff(poly,i);
48
49log10_2 = round(N * log(10) / log(2), wp, RN);
50log2_10 = log(2) / (N * log(10));
51log2_10_hi = round(log2_10, wp, RN);
52log2_10_lo = round(log2_10 - log2_10_hi, wp, RN);
53print(log10_2);
54print(log2_10_hi);
55print(log2_10_lo);
56