VirtualBox

source: vbox/trunk/src/VBox/VMM/tools/IEMGenFpuConstants.c@ 106814

Last change on this file since 106814 was 106061, checked in by vboxsync, 3 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.4 KB
Line 
1/* $Id: IEMGenFpuConstants.c 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * IEMGenFpuConstants - Generates FPU constants for IEMAllAImplC.cpp.
4 *
5 * Compile on linux: gcc -I../../../../include -DIN_RING3 IEMGenFpuConstants.c -lmpfr -g -o IEMGenFpuConstants
6 */
7
8/*
9 * Copyright (C) 2022-2024 Oracle and/or its affiliates.
10 *
11 * This file is part of VirtualBox base platform packages, as
12 * available from https://www.virtualbox.org.
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation, in version 3 of the
17 * License.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, see <https://www.gnu.org/licenses>.
26 *
27 * SPDX-License-Identifier: GPL-3.0-only
28 */
29
30
31/*********************************************************************************************************************************
32* Header Files *
33*********************************************************************************************************************************/
34#include <iprt/types.h>
35#include <iprt/assertcompile.h>
36#include <stdio.h>
37#define MPFR_WANT_FLOAT128
38#include <gmp.h>
39#include <mpfr.h>
40
41
42void PrintComment(const char *pszComment, va_list va, mpfr_srcptr pVal, bool fList)
43{
44 const char * const pszIndent = fList ? " " : "";
45 printf(fList ? " /* " : "/** ");
46 vprintf(pszComment, va);
47 printf("\n%s * base-10: ", pszIndent);
48 mpfr_out_str(stdout, 10, 0, pVal, MPFR_RNDD);
49 printf("\n%s * base-16: ", pszIndent);
50 mpfr_out_str(stdout, 16, 0, pVal, MPFR_RNDD);
51 printf("\n%s * base-2 : ", pszIndent);
52 mpfr_out_str(stdout, 2, 0, pVal, MPFR_RNDD);
53 printf(" */\n");
54}
55
56
57uint64_t BinStrToU64(const char *psz, size_t cch)
58{
59 uint64_t u = 0;
60 while (cch-- > 0)
61 {
62 u <<= 1;
63 u |= *psz++ == '1';
64 }
65 return u;
66}
67
68
69void PrintU128(mpfr_srcptr pVal, const char *pszVariable, const char *pszComment, ...)
70{
71 va_list va;
72 va_start(va, pszComment);
73 PrintComment(pszComment, va, pVal, !pszVariable);
74 va_end(va);
75 if (pszVariable)
76 printf("const RTUINT128U %s = ", pszVariable);
77 else
78 printf(" ");
79 mpfr_exp_t iExpBinary;
80 char *pszBinary = mpfr_get_str(NULL, &iExpBinary, 2, 0, pVal, MPFR_RNDD);
81 printf("RTUINT128_INIT_C(%#llx, %#llx)%s\n",
82 BinStrToU64(pszBinary, 64), BinStrToU64(&pszBinary[64], 64), pszVariable ? ";" : ",");
83 mpfr_free_str(pszBinary);
84}
85
86
87void PrintF128(mpfr_srcptr pVal, const char *pszVariable, const char *pszComment, ...)
88{
89 RTFLOAT128U r128;
90 *(_Float128 *)&r128 = mpfr_get_float128(pVal, MPFR_RNDD);
91
92 va_list va;
93 va_start(va, pszComment);
94 PrintComment(pszComment, va, pVal, !pszVariable);
95 va_end(va);
96 if (pszVariable)
97 printf("const RTFLOAT128U %s = ", pszVariable);
98 else
99 printf(" ");
100 printf("RTFLOAT128U_INIT_C(%d, 0x%012llx, 0x%016llx, 0x%04x)%s\n",
101 r128.s.fSign, r128.s64.uFractionHi, r128.s64.uFractionLo, r128.s64.uExponent, pszVariable ? ";" : ",");
102}
103
104
105int main(void)
106{
107 mpfr_t Val;
108
109 mpfr_init2(Val, 112 + 1);
110 mpfr_const_log2(Val, MPFR_RNDN);
111 PrintF128(Val, "g_r128Ln2", "The ln2 constant as 128-bit floating point value.");
112
113 mpfr_init2(Val, 128);
114 mpfr_const_log2(Val, MPFR_RNDN);
115 PrintU128(Val, "g_u128Ln2Mantissa", "High precision ln2 value.");
116
117 mpfr_t Val2;
118 mpfr_init2(Val2, 67);
119 mpfr_const_log2(Val2, MPFR_RNDN);
120 mpfr_set(Val, Val2, MPFR_RNDN);
121 PrintU128(Val, "g_u128Ln2MantissaIntel", "High precision ln2 value, compatible with f2xm1 results on intel 10980XE.");
122
123 /** @todo emit constants with 68-bit precision (1+67 bits), as that's what we
124 * use for intel now. */
125 printf("\n"
126 "/** Horner constants for f2xm1 */\n"
127 "const RTFLOAT128U g_ar128F2xm1HornerConsts[] =\n"
128 "{\n");
129 mpfr_t One;
130 mpfr_init2(One, 112 + 1);
131 mpfr_set_ui(One, 1, MPFR_RNDD);
132 PrintF128(One, NULL, "a0");
133
134 mpfr_init2(Val, 112 + 1);
135 mpfr_set_ui(Val, 1, MPFR_RNDD);
136 for (unsigned a = 1; a < 22; a++)
137 {
138 mpfr_div_ui(Val, Val, a + 1, MPFR_RNDD);
139 PrintF128(Val, NULL, "a%u", a);
140 }
141
142 printf("};\n");
143
144 mpfr_init2(Val, 112 + 1);
145 mpfr_const_pi(Val, MPFR_RNDN);
146 PrintF128(Val, "g_r128pi", "The pi constant as 128-bit floating point value.");
147 mpfr_div_ui(Val, Val, 2, MPFR_RNDD);
148 PrintF128(Val, "g_r128pi2", "The pi/2 constant as 128-bit floating point value.");
149
150 printf("\n"
151 "/** CORDIC constants for fsin and fcos, defined by c(i)=atan(2^(-i)) */\n"
152 "const RTFLOAT128U g_ar128FsincosCORDICConsts[] =\n"
153 "{\n");
154 mpfr_init2(Val, 112 + 1);
155 signed kmax = 68;
156
157 for (signed k = 0; k < kmax; k++)
158 {
159 // mpfr_mul_2si ?
160 mpfr_set_si_2exp(Val, 1, -k, MPFR_RNDD);
161 mpfr_atan(Val, Val, MPFR_RNDD);
162 PrintF128(Val, NULL, "c%u", k);
163 }
164
165 printf("};\n");
166
167 printf("\n"
168 "/** CORDIC multipliers for fsin and fcos, defined by K(i)=1/sqrt(1+2^(-2i)) */\n"
169 "const RTFLOAT128U g_ar128FsincosCORDICConsts2[] =\n"
170 "{\n");
171
172 mpfr_init2(Val, 112 + 1);
173 mpfr_init2(Val2, 112 + 1);
174
175 mpfr_set_ui(Val, 2, MPFR_RNDD);
176 mpfr_sqrt(Val, Val, MPFR_RNDD);
177 mpfr_ui_div(Val2, 1, Val, MPFR_RNDD);
178 PrintF128(Val2, NULL, "K_%u", 0);
179
180 for (signed k = 1; k < kmax; k++)
181 {
182 mpfr_set_si_2exp(Val, 1, -2 * k, MPFR_RNDD);
183 mpfr_add_ui(Val, Val, 1, MPFR_RNDD);
184 mpfr_sqrt(Val, Val, MPFR_RNDD);
185 mpfr_div(Val2, Val2, Val, MPFR_RNDD);
186 PrintF128(Val2, NULL, "K_%u", k);
187 }
188
189 printf("};\n");
190
191 printf("\n"
192 "/** Chebyshev coeffs for log2 function in [1, 2] interval */\n"
193 "const RTFLOAT128U g_ar128ChebLog2Consts[] =\n"
194 "{\n");
195 signed j, d, dmax = 22;
196 mpfr_t ValX, ValXX, ValA, ValB, ValBmA, ValCos, ValSum;
197 mpfr_init2(Val, 112 + 1);
198 mpfr_init2(Val2, 112 + 1);
199 mpfr_init2(ValX, 112 + 1);
200 mpfr_init2(ValXX, 112 + 1);
201 mpfr_init2(ValA, 112 + 1);
202 mpfr_init2(ValB, 112 + 1);
203 mpfr_init2(ValBmA, 112 + 1);
204 mpfr_init2(ValCos, 112 + 1);
205 mpfr_init2(ValSum, 112 + 1);
206
207 /* Setting the desired interpolation range [1.0, 2.0] */
208 mpfr_set_d(ValA, 1.0, MPFR_RNDD);
209 mpfr_set_d(ValB, 2.0, MPFR_RNDD);
210 mpfr_sub(ValBmA, ValB, ValA, MPFR_RNDD);
211
212 for (signed d = 0; d < dmax; d++)
213 {
214 mpfr_set_si(ValSum, 0, MPFR_RNDD);
215
216 for(j = 0; j < dmax; j++)
217 {
218 mpfr_set_si_2exp(Val, 1, -1, MPFR_RNDD);
219 mpfr_add_ui(Val, Val, j, MPFR_RNDD);
220 mpfr_const_pi(Val2, MPFR_RNDN);
221 mpfr_mul(Val, Val2, Val, MPFR_RNDN);
222 mpfr_div_si(Val, Val, dmax, MPFR_RNDN);
223 /* Val = M_PIq * (j + 0.5Q) / N */
224
225 mpfr_cos(ValX, Val, MPFR_RNDN);
226 /* ValX = cos(M_PIq * (j + 0.5Q) / N) */
227
228 mpfr_mul_si(Val, Val, d, MPFR_RNDN);
229 mpfr_cos(ValCos, Val, MPFR_RNDN);
230 /* ValCos = cos(M_PIq * d * (j + 0.5Q) / N) */
231
232 mpfr_add_si(Val, ValX, 1, MPFR_RNDN);
233 mpfr_div_si(Val, Val, 2, MPFR_RNDN);
234 mpfr_mul(Val, ValBmA, Val, MPFR_RNDN);
235 mpfr_add(ValXX, ValA, Val, MPFR_RNDN);
236 /* ValXX = a + (b - a) * (x + 1.0Q) / 2.0Q */
237
238 mpfr_sub_si(Val, ValXX, 1, MPFR_RNDN);
239 mpfr_log2(Val2, ValXX, MPFR_RNDN);
240 mpfr_div(Val, Val2, Val, MPFR_RNDN);
241 mpfr_mul(Val, Val, ValCos, MPFR_RNDN);
242 mpfr_add(ValSum, ValSum, Val, MPFR_RNDN);
243 }
244
245 mpfr_div_si(ValSum, ValSum, dmax, MPFR_RNDN);
246
247 if (d != 0)
248 mpfr_mul_si(ValSum, ValSum, 2, MPFR_RNDN);
249
250 PrintF128(ValSum, NULL, "c%u", d);
251 }
252
253 printf("};\n");
254
255 mpfr_init2(One, 112 + 1);
256 mpfr_set_ui(One, 1, MPFR_RNDD);
257
258 mpfr_init2(Val, 112 + 1);
259 mpfr_exp(Val, One, MPFR_RNDD);
260 mpfr_log2(Val, Val, MPFR_RNDD);
261
262 PrintF128(Val, "g_r128Log2e", "The log2e constant as 128-bit floating point value.");
263
264 mpfr_clear(ValXX);
265 mpfr_clear(ValX);
266 mpfr_clear(Val);
267 mpfr_clear(Val2);
268 mpfr_clear(One);
269 mpfr_free_cache();
270 return 0;
271}
272
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette