You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
3.9 KiB
103 lines
3.9 KiB
// binary operator *
|
|
|
|
// General includes.
|
|
#include "base/cl_sysdep.h"
|
|
|
|
// Specification.
|
|
#include "cln/ffloat.h"
|
|
|
|
|
|
// Implementation.
|
|
|
|
#include "float/ffloat/cl_FF.h"
|
|
#include "float/cl_F.h"
|
|
#include "base/cl_low.h"
|
|
|
|
#include "base/cl_inline.h"
|
|
#include "float/ffloat/elem/cl_FF_zerop.cc"
|
|
|
|
namespace cln {
|
|
|
|
|
|
const cl_FF operator* (const cl_FF& x1, const cl_FF& x2)
|
|
{
|
|
// Methode:
|
|
// Falls x1=0.0 oder x2=0.0 -> Ergebnis 0.0
|
|
// Sonst: Ergebnis-Vorzeichen = VZ von x1 xor VZ von x2.
|
|
// Ergebnis-Exponent = Summe der Exponenten von x1 und x2.
|
|
// Ergebnis-Mantisse = Produkt der Mantissen von x1 und x2, gerundet:
|
|
// 2^-24 * mant1 * 2^-24 * mant2 = 2^-48 * (mant1*mant2),
|
|
// die Klammer ist >=2^46, <=(2^24-1)^2<2^48 .
|
|
// Falls die Klammer >=2^47 ist, um 24 Bit nach rechts schieben und
|
|
// runden: Falls Bit 23 Null, abrunden; falls Bit 23 Eins und
|
|
// Bits 22..0 alle Null, round-to-even; sonst aufrunden.
|
|
// Falls die Klammer <2^47 ist, um 23 Bit nach rechts schieben und
|
|
// runden: Falls Bit 22 Null, abrunden; falls Bit 22 Eins und
|
|
// Bits 21..0 alle Null, round-to-even; sonst aufrunden. Nach
|
|
// Aufrunden: Falls =2^24, um 1 Bit nach rechts schieben. Sonst
|
|
// Exponenten um 1 erniedrigen.
|
|
#ifdef FAST_FLOAT
|
|
float_to_FF(FF_to_float(x1) * FF_to_float(x2), return ,
|
|
TRUE, TRUE, // Overflow und subnormale Zahl abfangen
|
|
!(zerop_inline(x1) || zerop_inline(x2)), // ein Ergebnis +/- 0.0
|
|
// ist genau dann in Wirklichkeit ein Underflow
|
|
FALSE, FALSE // keine Singularität, 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(x1, { return x1; }, sign1=,exp1=,mant1=);
|
|
FF_decode(x2, { return x2; }, sign2=,exp2=,mant2=);
|
|
exp1 = exp1 + exp2; // Summe der Exponenten
|
|
sign1 = sign1 ^ sign2; // Ergebnis-Vorzeichen
|
|
var uintL manthi;
|
|
var uintL mantlo;
|
|
// Mantissen mant1 und mant2 multiplizieren:
|
|
mulu24(mant1,mant2, manthi=,mantlo=);
|
|
manthi = (manthi << (32-FF_mant_len)) | (mantlo >> FF_mant_len);
|
|
mantlo = mantlo & (bit(FF_mant_len)-1);
|
|
// Nun ist 2^FF_mant_len * manthi + mantlo = mant1 * mant2.
|
|
if (manthi >= bit(FF_mant_len+1))
|
|
// mant1*mant2 >= 2^(2*FF_mant_len+1)
|
|
{ if ( ((manthi & bit(0)) ==0) // Bit FF_mant_len =0 -> abrunden
|
|
|| ( (mantlo ==0) // Bit FF_mant_len =1 und Bits FF_mant_len-1..0 >0 -> aufrunden
|
|
// round-to-even, je nach Bit FF_mant_len+1 :
|
|
&& ((manthi & bit(1)) ==0)
|
|
) )
|
|
// abrunden
|
|
{ manthi = manthi >> 1; goto ab; }
|
|
else
|
|
// aufrunden
|
|
{ manthi = manthi >> 1; goto auf; }
|
|
}
|
|
else
|
|
// mant1*mant2 < 2^(2*FF_mant_len+1)
|
|
{ exp1 = exp1-1; // Exponenten decrementieren
|
|
if ( ((mantlo & bit(FF_mant_len-1)) ==0) // Bit FF_mant_len-1 =0 -> abrunden
|
|
|| ( ((mantlo & (bit(FF_mant_len-1)-1)) ==0) // Bit FF_mant_len-1 =1 und Bits FF_mant_len-2..0 >0 -> aufrunden
|
|
// round-to-even, je nach Bit FF_mant_len :
|
|
&& ((manthi & bit(0)) ==0)
|
|
) )
|
|
// abrunden
|
|
goto ab;
|
|
else
|
|
// aufrunden
|
|
goto auf;
|
|
}
|
|
auf:
|
|
manthi = manthi+1;
|
|
// Hier ist 2^FF_mant_len <= manthi <= 2^(FF_mant_len+1)
|
|
if (manthi >= bit(FF_mant_len+1)) // rounding overflow?
|
|
{ manthi = manthi>>1; exp1 = exp1+1; } // Shift nach rechts
|
|
ab:
|
|
// Runden fertig, 2^FF_mant_len <= manthi < 2^(FF_mant_len+1)
|
|
return encode_FF(sign1,exp1,manthi);
|
|
#endif
|
|
}
|
|
|
|
} // namespace cln
|