Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
f64_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 f64_rem.c:

Go to the source code of this file.

Functions

float64_t f64_rem (float64_t a, float64_t b)
 

Function Documentation

◆ f64_rem()

float64_t f64_rem ( float64_t a,
float64_t b )

Definition at line 44 of file f64_rem.c.

45{
46 union ui64_f64 uA;
47 uint_fast64_t uiA;
48 bool signA;
49 int_fast16_t expA;
50 uint_fast64_t sigA;
51 union ui64_f64 uB;
52 uint_fast64_t uiB;
53 int_fast16_t expB;
54 uint_fast64_t sigB;
55 struct exp16_sig64 normExpSig;
56 uint64_t rem;
57 int_fast16_t expDiff;
58 uint32_t q, recip32;
59 uint_fast64_t q64;
60 uint64_t altRem, meanRem;
61 bool signRem;
62 uint_fast64_t uiZ;
63 union ui64_f64 uZ;
64
65 /*------------------------------------------------------------------------
66 *------------------------------------------------------------------------*/
67 uA.f = a;
68 uiA = uA.ui;
69 signA = signF64UI( uiA );
70 expA = expF64UI( uiA );
71 sigA = fracF64UI( uiA );
72 uB.f = b;
73 uiB = uB.ui;
74 expB = expF64UI( uiB );
75 sigB = fracF64UI( uiB );
76 /*------------------------------------------------------------------------
77 *------------------------------------------------------------------------*/
78 if ( expA == 0x7FF ) {
79 if ( sigA || ((expB == 0x7FF) && sigB) ) goto propagateNaN;
80 goto invalid;
81 }
82 if ( expB == 0x7FF ) {
83 if ( sigB ) goto propagateNaN;
84 return a;
85 }
86 /*------------------------------------------------------------------------
87 *------------------------------------------------------------------------*/
88 if ( expA < expB - 1 ) return a;
89 /*------------------------------------------------------------------------
90 *------------------------------------------------------------------------*/
91 if ( ! expB ) {
92 if ( ! sigB ) goto invalid;
93 normExpSig = softfloat_normSubnormalF64Sig( sigB );
94 expB = normExpSig.exp;
95 sigB = normExpSig.sig;
96 }
97 if ( ! expA ) {
98 if ( ! sigA ) return a;
99 normExpSig = softfloat_normSubnormalF64Sig( sigA );
100 expA = normExpSig.exp;
101 sigA = normExpSig.sig;
102 }
103 /*------------------------------------------------------------------------
104 *------------------------------------------------------------------------*/
105 rem = sigA | UINT64_C( 0x0010000000000000 );
106 sigB |= UINT64_C( 0x0010000000000000 );
107 expDiff = expA - expB;
108 if ( expDiff < 1 ) {
109 if ( expDiff < -1 ) return a;
110 sigB <<= 9;
111 if ( expDiff ) {
112 rem <<= 8;
113 q = 0;
114 } else {
115 rem <<= 9;
116 q = (sigB <= rem);
117 if ( q ) rem -= sigB;
118 }
119 } else {
120 recip32 = softfloat_approxRecip32_1( sigB>>21 );
121 /*--------------------------------------------------------------------
122 | Changing the shift of `rem' here requires also changing the initial
123 | subtraction from `expDiff'.
124 *--------------------------------------------------------------------*/
125 rem <<= 9;
126 expDiff -= 30;
127 /*--------------------------------------------------------------------
128 | The scale of `sigB' affects how many bits are obtained during each
129 | cycle of the loop. Currently this is 29 bits per loop iteration,
130 | the maximum possible.
131 *--------------------------------------------------------------------*/
132 sigB <<= 9;
133 for (;;) {
134 q64 = (uint32_t) (rem>>32) * (uint_fast64_t) recip32;
135 if ( expDiff < 0 ) break;
136 q = (q64 + 0x80000000)>>32;
137#ifdef SOFTFLOAT_FAST_INT64
138 rem <<= 29;
139#else
140 rem = (uint_fast64_t) (uint32_t) (rem>>3)<<32;
141#endif
142 rem -= q * (uint64_t) sigB;
143 if ( rem & UINT64_C( 0x8000000000000000 ) ) rem += sigB;
144 expDiff -= 29;
145 }
146 /*--------------------------------------------------------------------
147 | (`expDiff' cannot be less than -29 here.)
148 *--------------------------------------------------------------------*/
149 q = (uint32_t) (q64>>32)>>(~expDiff & 31);
150 rem = (rem<<(expDiff + 30)) - q * (uint64_t) sigB;
151 if ( rem & UINT64_C( 0x8000000000000000 ) ) {
152 altRem = rem + sigB;
153 goto selectRem;
154 }
155 }
156 /*------------------------------------------------------------------------
157 *------------------------------------------------------------------------*/
158 do {
159 altRem = rem;
160 ++q;
161 rem -= sigB;
162 } while ( ! (rem & UINT64_C( 0x8000000000000000 )) );
163 selectRem:
164 meanRem = rem + altRem;
165 if (
166 (meanRem & UINT64_C( 0x8000000000000000 )) || (! meanRem && (q & 1))
167 ) {
168 rem = altRem;
169 }
170 signRem = signA;
171 if ( rem & UINT64_C( 0x8000000000000000 ) ) {
172 signRem = ! signRem;
173 rem = -rem;
174 }
175 return softfloat_normRoundPackToF64( signRem, expB, rem );
176 /*------------------------------------------------------------------------
177 *------------------------------------------------------------------------*/
178 propagateNaN:
179 uiZ = softfloat_propagateNaNF64UI( uiA, uiB );
180 goto uiZ;
181 invalid:
183 uiZ = defaultNaNF64UI;
184 uiZ:
185 uZ.ui = uiZ;
186 return uZ.f;
187
188}
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1181
uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB)
void softfloat_raiseFlags(uint_fast8_t flags)
#define defaultNaNF64UI
Definition specialize.h:158
struct exp16_sig64 softfloat_normSubnormalF64Sig(uint_fast64_t)
#define signF64UI(a)
Definition internals.h:125
float64_t softfloat_normRoundPackToF64(bool, int_fast16_t, uint_fast64_t)
#define expF64UI(a)
Definition internals.h:126
#define fracF64UI(a)
Definition internals.h:127
uint32_t softfloat_approxRecip32_1(uint32_t a)
@ softfloat_flag_invalid
Definition softfloat.h:89
unsigned int uint32_t
Definition stdint.h:126
uint64_t uint_fast64_t
Definition stdint.h:157
#define UINT64_C(val)
Definition stdint.h:284
int16_t int_fast16_t
Definition stdint.h:151
unsigned __int64 uint64_t
Definition stdint.h:136
float64_t f
Definition internals.h:47
Here is the call graph for this function: