Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
extF80_rem.c File Reference
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
Include dependency graph for extF80_rem.c:

Go to the source code of this file.

Functions

extFloat80_t extF80_rem (extFloat80_t a, extFloat80_t b)
 

Function Documentation

◆ extF80_rem()

extFloat80_t extF80_rem ( extFloat80_t a,
extFloat80_t b )

Definition at line 44 of file extF80_rem.c.

45{
46 union { struct extFloat80M s; extFloat80_t f; } uA;
47 uint_fast16_t uiA64;
48 uint_fast64_t uiA0;
49 bool signA;
50 int_fast32_t expA;
51 uint_fast64_t sigA;
52 union { struct extFloat80M s; extFloat80_t f; } uB;
53 uint_fast16_t uiB64;
54 uint_fast64_t uiB0;
55 int_fast32_t expB;
56 uint_fast64_t sigB;
57 struct exp32_sig64 normExpSig;
58 int_fast32_t expDiff;
59 struct uint128 rem, shiftedSigB;
60 uint_fast32_t q, recip32;
61 uint_fast64_t q64;
62 struct uint128 term, altRem, meanRem;
63 bool signRem;
64 struct uint128 uiZ;
65 uint_fast16_t uiZ64;
66 uint_fast64_t uiZ0;
67 union { struct extFloat80M s; extFloat80_t f; } uZ;
68
69 /*------------------------------------------------------------------------
70 *------------------------------------------------------------------------*/
71 uA.f = a;
72 uiA64 = uA.s.signExp;
73 uiA0 = uA.s.signif;
74 signA = signExtF80UI64( uiA64 );
75 expA = expExtF80UI64( uiA64 );
76 sigA = uiA0;
77 uB.f = b;
78 uiB64 = uB.s.signExp;
79 uiB0 = uB.s.signif;
80 expB = expExtF80UI64( uiB64 );
81 sigB = uiB0;
82 /*------------------------------------------------------------------------
83 *------------------------------------------------------------------------*/
84 if ( expA == 0x7FFF ) {
85 if (
86 (sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
87 || ((expB == 0x7FFF) && (sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF )))
88 ) {
89 goto propagateNaN;
90 }
91 goto invalid;
92 }
93 if ( expB == 0x7FFF ) {
94 if ( sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN;
95 /*--------------------------------------------------------------------
96 | Argument b is an infinity. Doubling `expB' is an easy way to ensure
97 | that `expDiff' later is less than -1, which will result in returning
98 | a canonicalized version of argument a.
99 *--------------------------------------------------------------------*/
100 expB += expB;
101 }
102 /*------------------------------------------------------------------------
103 *------------------------------------------------------------------------*/
104 if ( ! expB ) expB = 1;
105 if ( ! (sigB & UINT64_C( 0x8000000000000000 )) ) {
106 if ( ! sigB ) goto invalid;
107 normExpSig = softfloat_normSubnormalExtF80Sig( sigB );
108 expB += normExpSig.exp;
109 sigB = normExpSig.sig;
110 }
111 if ( ! expA ) expA = 1;
112 if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) {
113 if ( ! sigA ) {
114 expA = 0;
115 goto copyA;
116 }
117 normExpSig = softfloat_normSubnormalExtF80Sig( sigA );
118 expA += normExpSig.exp;
119 sigA = normExpSig.sig;
120 }
121 /*------------------------------------------------------------------------
122 *------------------------------------------------------------------------*/
123 expDiff = expA - expB;
124 if ( expDiff < -1 ) goto copyA;
125 rem = softfloat_shortShiftLeft128( 0, sigA, 32 );
126 shiftedSigB = softfloat_shortShiftLeft128( 0, sigB, 32 );
127 if ( expDiff < 1 ) {
128 if ( expDiff ) {
129 --expB;
130 shiftedSigB = softfloat_shortShiftLeft128( 0, sigB, 33 );
131 q = 0;
132 } else {
133 q = (sigB <= sigA);
134 if ( q ) {
135 rem =
137 rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0 );
138 }
139 }
140 } else {
141 recip32 = softfloat_approxRecip32_1( sigB>>32 );
142 expDiff -= 30;
143 for (;;) {
144 q64 = (uint_fast64_t) (uint32_t) (rem.v64>>2) * recip32;
145 if ( expDiff < 0 ) break;
146 q = (q64 + 0x80000000)>>32;
147 rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
148 term = softfloat_mul64ByShifted32To128( sigB, q );
149 rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
150 if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
151 rem =
153 rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0 );
154 }
155 expDiff -= 29;
156 }
157 /*--------------------------------------------------------------------
158 | (`expDiff' cannot be less than -29 here.)
159 *--------------------------------------------------------------------*/
160 q = (uint32_t) (q64>>32)>>(~expDiff & 31);
161 rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, expDiff + 30 );
162 term = softfloat_mul64ByShifted32To128( sigB, q );
163 rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
164 if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
165 altRem =
167 rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0 );
168 goto selectRem;
169 }
170 }
171 /*------------------------------------------------------------------------
172 *------------------------------------------------------------------------*/
173 do {
174 altRem = rem;
175 ++q;
176 rem =
178 rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0 );
179 } while ( ! (rem.v64 & UINT64_C( 0x8000000000000000 )) );
180 selectRem:
181 meanRem = softfloat_add128( rem.v64, rem.v0, altRem.v64, altRem.v0 );
182 if (
183 (meanRem.v64 & UINT64_C( 0x8000000000000000 ))
184 || (! (meanRem.v64 | meanRem.v0) && (q & 1))
185 ) {
186 rem = altRem;
187 }
188 signRem = signA;
189 if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
190 signRem = ! signRem;
191 rem = softfloat_sub128( 0, 0, rem.v64, rem.v0 );
192 }
193 return
195 signRem, rem.v64 | rem.v0 ? expB + 32 : 0, rem.v64, rem.v0, 80 );
196 /*------------------------------------------------------------------------
197 *------------------------------------------------------------------------*/
198 propagateNaN:
199 uiZ = softfloat_propagateNaNExtF80UI( uiA64, uiA0, uiB64, uiB0 );
200 uiZ64 = uiZ.v64;
201 uiZ0 = uiZ.v0;
202 goto uiZ;
203 /*------------------------------------------------------------------------
204 *------------------------------------------------------------------------*/
205 invalid:
207 uiZ64 = defaultNaNExtF80UI64;
208 uiZ0 = defaultNaNExtF80UI0;
209 goto uiZ;
210 /*------------------------------------------------------------------------
211 *------------------------------------------------------------------------*/
212 copyA:
213 if ( expA < 1 ) {
214 sigA >>= 1 - expA;
215 expA = 0;
216 }
217 uiZ64 = packToExtF80UI64( signA, expA );
218 uiZ0 = sigA;
219 uiZ:
220 uZ.s.signExp = uiZ64;
221 uZ.s.signif = uiZ0;
222 return uZ.f;
223
224}
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1181
struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0)
void softfloat_raiseFlags(uint_fast8_t flags)
#define defaultNaNExtF80UI0
Definition specialize.h:194
#define defaultNaNExtF80UI64
Definition specialize.h:193
#define packToExtF80UI64(sign, exp)
Definition internals.h:148
#define expExtF80UI64(a64)
Definition internals.h:147
#define signExtF80UI64(a64)
Definition internals.h:146
uint32_t softfloat_approxRecip32_1(uint32_t a)
@ softfloat_flag_invalid
Definition softfloat.h:89
struct uint128 softfloat_add128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0)
Definition s_add128.c:44
struct uint128 softfloat_mul64ByShifted32To128(uint64_t a, uint32_t b)
extFloat80_t softfloat_normRoundPackToExtF80(bool sign, int_fast32_t exp, uint_fast64_t sig, uint_fast64_t sigExtra, uint_fast8_t roundingPrecision)
struct exp32_sig64 softfloat_normSubnormalExtF80Sig(uint_fast64_t sig)
struct uint128 softfloat_shortShiftLeft128(uint64_t a64, uint64_t a0, uint_fast8_t dist)
struct uint128 softfloat_sub128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0)
Definition s_sub128.c:44
unsigned int uint32_t
Definition stdint.h:126
uint16_t uint_fast16_t
Definition stdint.h:155
uint64_t uint_fast64_t
Definition stdint.h:157
#define UINT64_C(val)
Definition stdint.h:284
uint32_t uint_fast32_t
Definition stdint.h:156
int32_t int_fast32_t
Definition stdint.h:152
uint16_t signExp
char * s
Here is the call graph for this function: