// binary operator /
// General includes.
#include "cl_sysdep.h"
// Specification.
#include "cln/ffloat.h"
// Implementation.
#include "cl_FF.h"
#include "cl_N.h"
#include "cl_F.h"
#include "cl_low.h"
#include "cl_ieee.h"
#undef MAYBE_INLINE
#define MAYBE_INLINE inline
#include "cl_FF_zerop.cc"
namespace cln {
NEED_IEEE_FLOATS()
const cl_FF operator/ (const cl_FF& x1, const cl_FF& x2)
{
// Methode:
// x2 = 0.0 -> Error
// x1 = 0.0 -> Ergebnis 0.0
// Sonst:
// Ergebnis-Vorzeichen = xor der beiden Vorzeichen von x1 und x2
// Ergebnis-Exponent = Differenz der beiden Exponenten von x1 und x2
// Ergebnis-Mantisse = Mantisse mant1 / Mantisse mant2, gerundet.
// mant1/mant2 > 1/2, mant1/mant2 < 2;
// nach Rundung mant1/mant2 >=1/2, <=2*mant1<2.
// Bei mant1/mant2 >=1 brauche 23 Nachkommabits,
// bei mant1/mant2 <1 brauche 24 Nachkommabits.
// Fürs Runden: brauche ein Rundungsbit (Rest gibt an, ob exakt).
// Brauche daher insgesamt 25 Nachkommabits von mant1/mant2.
// Dividiere daher (als Unsigned Integers) 2^25*(2^24*mant1) durch (2^24*mant2).
// Falls der Quotient >=2^25 ist, runde die letzten zwei Bits weg und
// erhöhe den Exponenten um 1.
// Falls der Quotient <2^25 ist, runde das letzte Bit weg. Bei rounding
// overflow schiebe um ein weiteres Bit nach rechts, incr. Exponenten.
#if defined(FAST_FLOAT) && !defined(__i386__)
float_to_FF(FF_to_float(x1) / FF_to_float(x2), return ,
TRUE, TRUE, // Overflow und subnormale Zahl abfangen
!zerop(x1), // ein Ergebnis +/- 0.0
// ist genau dann in Wirklichkeit ein Underflow
zerop(x2), // Division durch Null abfangen
FALSE // kein NaN als Ergebnis möglich
);
#else
// x1,x2 entpacken:
var cl_signean sign1;
var sintL exp1;
var uintL mant1;
var cl_signean sign2;
var sintL exp2;
var uintL mant2;
FF_decode(x2, { cl_error_division_by_0(); }, sign2=,exp2=,mant2=);
FF_decode(x1, { return x1; }, sign1=,exp1=,mant1=);
exp1 = exp1 - exp2; // Differenz der Exponenten
sign1 = sign1 ^ sign2; // Ergebnis-Vorzeichen
// Dividiere 2^25*mant1 durch mant2 oder (äquivalent)
// 2^i*2^25*mant1 durch 2^i*mant2 für irgendein i mit 0 <= i <= 32-24 :
var uintL mant;
var uintL rest;
// wähle i = 32-(FF_mant_len+1), also i+(FF_mant_len+2) = 33.
divu_6432_3232(mant1<<1,0, mant2<<(32-(FF_mant_len+1)), mant=,rest=);
if (mant >= bit(FF_mant_len+2))
// Quotient >=2^25 -> 2 Bits wegrunden
{ var uintL rounding_bits = mant & (bit(2)-1);
exp1 += 1; // Exponenten incrementieren
mant = mant >> 2;
if ( (rounding_bits < bit(1)) // 00,01 werden abgerundet
|| ( (rounding_bits == bit(1)) // 10
&& (rest == 0) // und genau halbzahlig
&& ((mant & bit(0)) ==0) // -> round-to-even
) )
// abrunden
{}
else
// aufrunden
{ mant += 1; }
}
else
// Quotient <2^25 -> 1 Bit wegrunden
{ var uintL rounding_bit = mant & bit(0);
mant = mant >> 1;
if ( (rounding_bit == 0) // 0 wird abgerundet
|| ( (rest == 0) // genau halbzahlig
&& ((mant & bit(0)) ==0) // -> round-to-even
) )
// abrunden
{}
else
// aufrunden
{ mant += 1;
if (mant >= bit(FF_mant_len+1)) // rounding overflow?
{ mant = mant>>1; exp1 = exp1+1; }
} }
return encode_FF(sign1,exp1,mant);
#endif
}
} // namespace cln
syntax highlighted by Code2HTML, v. 0.9.1