VirtualBox

source: vbox/trunk/src/libs/softfloat-3e/source/extF80_sincos.c@ 96673

Last change on this file since 96673 was 96666, checked in by vboxsync, 2 years ago

libs/softfloat-3e: Build fixes and cleanups for the sincos code. [build fix] bugref:9898

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.9 KB
Line 
1/* $Id: extF80_sincos.c 96666 2022-09-08 22:34:41Z vboxsync $ */
2/** @file
3 * SoftFloat - VBox Extension - extF80_sin, extF80_cos, extF80_sincos.
4 */
5
6/*
7 * Copyright (C) 2022 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#include <stdbool.h>
33#include <stdint.h>
34#include "platform.h"
35#include "internals.h"
36#include "specialize.h"
37#include "softfloat.h"
38#include <iprt/types.h>
39#include <iprt/x86.h>
40
41#include "extF80_sincos.h"
42
43
44static void cordic_sincos( float128_t z, float128_t *pv1, float128_t *pv2 SOFTFLOAT_STATE_DECL_COMMA )
45{
46 float128_t v1 = { { 0, 0 } }; /* MSC thinks it can be used uninitialized */
47 float128_t v2 = { { 0, 0 } }; /* MSC thinks it can be used uninitialized */
48 /** @todo TBD: CORDIC kernel should be easily implemented in assembly * */
49
50 float128_t x1 = ui32_to_f128(1, pState);
51 float128_t x2 = ui32_to_f128(0, pState);
52 float128_t zz = ui32_to_f128(0, pState);
53
54 float128_t p2m = ui32_to_f128(1, pState);
55 float128_t two = ui32_to_f128(2, pState);
56
57 for (unsigned k = 0; k < RT_ELEMENTS(g_ar128FsincosCORDICConsts); k++)
58 {
59 float128_t atg = *(float128_t *)&g_ar128FsincosCORDICConsts[k];
60 float128_t scale = *(float128_t *)&g_ar128FsincosCORDICConsts2[k];
61
62 float128_t px1 = f128_mul(x1, p2m, pState);
63 float128_t px2 = f128_mul(x2, p2m, pState);
64
65 if (f128_le(zz, z, pState))
66 {
67 x1 = f128_sub(x1, px2, pState);
68 x2 = f128_add(x2, px1, pState);
69 zz = f128_add(zz, atg, pState);
70 }
71 else
72 {
73 x1 = f128_add(x1, px2, pState);
74 x2 = f128_sub(x2, px1, pState);
75 zz = f128_sub(zz, atg, pState);
76 }
77
78 p2m = f128_div(p2m, two, pState);
79
80 v1 = f128_mul(x1, scale, pState);
81 v2 = f128_mul(x2, scale, pState);
82 }
83
84 *pv1 = v1;
85 *pv2 = v2;
86}
87
88extFloat80_t extF80_sin( extFloat80_t x SOFTFLOAT_STATE_DECL_COMMA )
89{
90 int32_t fSign = 0;
91 extFloat80_t f80zero = ui32_to_extF80(0, pState);
92 if (extF80_le(x, f80zero, pState))
93 {
94 x = extF80_sub(f80zero, x, pState);
95 fSign = 1;
96 }
97
98 extFloat80_t f80pi2 = f128_to_extF80(*(float128_t *)&g_r128pi2, pState);
99
100 /** @todo TBD: Partial remainder should be calculated using float128 value of pi2 to increase precision **/
101 uint16_t fCxFlags = 0;
102 extFloat80_t rem = extF80_partialRem(x, f80pi2, pState->roundingMode, &fCxFlags, pState);
103 int32_t const quo = X86_FSW_CX_TO_QUOTIENT(fCxFlags);
104
105 float128_t z = extF80_to_f128(rem, pState);
106 float128_t f128zero = ui32_to_f128(0, pState);
107
108 float128_t v1, v2;
109 cordic_sincos(z, &v1, &v2, pState);
110
111 float128_t v;
112 switch(quo % 4)
113 {
114#ifdef _MSC_VER /* stupid MSC thinks v might be used uninitialized otherwise: */
115 default:
116#endif
117 case 0:
118 v = v2;
119 break;
120
121 case 1:
122 v = v1;
123 break;
124
125 case 2:
126 v = f128_sub(f128zero, v2, pState);
127 break;
128
129 case 3:
130 v = f128_sub(f128zero, v1, pState);
131 break;
132 }
133
134 if (fSign)
135 v = f128_sub(f128zero, v, pState);
136
137 return f128_to_extF80(v, pState);
138}
139
140extFloat80_t extF80_cos( extFloat80_t x SOFTFLOAT_STATE_DECL_COMMA )
141{
142 extFloat80_t f80zero = ui32_to_extF80(0, pState);
143 if (extF80_le(x, f80zero, pState))
144 x = extF80_sub(f80zero, x, pState);
145
146 extFloat80_t f80pi2 = f128_to_extF80(*(float128_t *)&g_r128pi2, pState);
147
148 /** TBD: Partial remainder should be calculated using float128 value of pi2 to increase precision **/
149 uint16_t fCxFlags = 0;
150 extFloat80_t rem = extF80_partialRem(x, f80pi2, pState->roundingMode, &fCxFlags, pState);
151 int32_t const quo = X86_FSW_CX_TO_QUOTIENT(fCxFlags);
152
153 float128_t z = extF80_to_f128(rem, pState);
154 float128_t f128zero = ui32_to_f128(0, pState);
155
156 float128_t v1, v2;
157 cordic_sincos(z, &v1, &v2, pState);
158
159 float128_t v;
160 switch(quo % 4)
161 {
162#ifdef _MSC_VER /* stupid MSC thinks v might be used uninitialized otherwise: */
163 default:
164#endif
165 case 0:
166 v = v1;
167 break;
168
169 case 1:
170 v = f128_sub(f128zero, v2, pState);;
171 break;
172
173 case 2:
174 v = f128_sub(f128zero, v1, pState);
175 break;
176
177 case 3:
178 v = v2;
179 break;
180 }
181
182 return f128_to_extF80(v, pState);
183}
184
185void extF80_sincos( extFloat80_t x, extFloat80_t* pSin, extFloat80_t* pCos SOFTFLOAT_STATE_DECL_COMMA )
186{
187 uint16_t fCxFlags = 0;
188 int32_t quo;
189 extFloat80_t rem, f80pi2, f80zero;
190 int32_t fSign = 0;
191
192 f80zero = ui32_to_extF80(0, pState);
193 if (extF80_le(x, f80zero, pState))
194 {
195 x = extF80_sub(f80zero, x, pState);
196 fSign = 1;
197 }
198
199 f80pi2 = f128_to_extF80(*(float128_t const *)&g_r128pi2, pState);
200
201 /** @todo TBD: Partial remainder should be calculated using float128 value of pi2 to increase precision **/
202 rem = extF80_partialRem(x, f80pi2, pState->roundingMode, &fCxFlags, pState);
203 quo = X86_FSW_CX_TO_QUOTIENT(fCxFlags);
204
205 float128_t z = extF80_to_f128(rem, pState);
206 float128_t f128zero = ui32_to_f128(0, pState);
207
208 float128_t v1, v2;
209 cordic_sincos(z, &v1, &v2, pState);
210
211 float128_t vCos, vSin;
212 switch(quo % 4)
213 {
214#ifdef _MSC_VER /* stupid MSC thinks vCos & cSin might be used uninitialized otherwise: */
215 default:
216#endif
217 case 0:
218 vCos = v1;
219 vSin = v2;
220 break;
221
222 case 1:
223 vCos = f128_sub(f128zero, v2, pState);
224 vSin = v1;
225 break;
226
227 case 2:
228 vCos = f128_sub(f128zero, v1, pState);
229 vSin = f128_sub(f128zero, v2, pState);
230 break;
231
232 case 3:
233 vCos = v2;
234 vSin = f128_sub(f128zero, v1, pState);
235 break;
236 }
237
238 if (fSign)
239 vSin = f128_sub(f128zero, vSin, pState);
240
241 *pCos = f128_to_extF80(vCos, pState);
242 *pSin = f128_to_extF80(vSin, pState);
243}
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