]> www.ginac.de Git - cln.git/blob - src/float/sfloat/cl_SF.h
Fix linking problems on some platforms caused by inline/non-inline versions
[cln.git] / src / float / sfloat / cl_SF.h
1 // cl_SF internals
2
3 #ifndef _CL_SF_H
4 #define _CL_SF_H
5
6 #include "cln/number.h"
7 #include "cl_F.h"
8
9 namespace cln {
10
11 // The immediate word contains:
12 //   |..|.......|..........................|....|
13 //  sign exponent             mantissa      tag
14
15   #define SF_value_shift 7      // could also be = cl_value_shift
16   #define SF_exp_len    8       // number of bits in the exponent
17   #define SF_mant_len  16       // number of bits in the mantissa
18                                 // (excluding the hidden bit)
19   #define SF_mant_hiddenbit 1   // yes, we have a hidden bit representation
20                                 // (this is hardwired in some of the code)
21   #define SF_exp_low   1                        // minimum exponent
22   #define SF_exp_mid   bit(SF_exp_len-1)        // exponent bias
23   #define SF_exp_high  (bit(SF_exp_len)-1)      // maximum exponent
24   #define SF_exp_shift  (SF_mant_len+SF_mant_shift) // lowest exponent bit
25   #define SF_mant_shift  SF_value_shift             // lowest mantissa bit
26   #define SF_sign_shift  (cl_pointer_size - 1)
27
28 // Builds a float from the immediate word.
29 inline cl_SF::cl_SF (struct cl_sfloat * null, cl_uint w)
30         : cl_F ((cl_private_thing) w) { unused null; }
31 inline const cl_SF cl_SF_from_word (cl_uint word)
32 {
33         return cl_SF((struct cl_sfloat *) 0, word);
34 }
35
36 // Builds a float word from sign (0 or -1), exponent and mantissa.
37 inline cl_uint make_SF_word (cl_sint sign, unsigned int exp, cl_uint mant)
38 {
39         return (sign & ((cl_uint)1 << SF_sign_shift))
40                | (exp << SF_exp_shift)
41                #if SF_mant_hiddenbit
42                | ((mant & (bit(SF_mant_len)-1)) << SF_mant_shift)
43                #else
44                | (mant << SF_mant_shift)
45                #endif
46                | (cl_SF_tag << cl_tag_shift);
47 }
48
49 // Builds a float from sign (0 or -1), exponent and mantissa.
50 inline const cl_SF make_SF (cl_sint sign, unsigned int exp, cl_uint mant)
51 {
52         return cl_SF_from_word(make_SF_word(sign,exp,mant));
53 }
54
55 // Short Float 0.0
56   #define SF_0  make_SF(0,0,0)
57 // Short Float 1.0
58   #define SF_1  make_SF(0,SF_exp_mid+1,bit(SF_mant_len))
59 // Short Float -1.0
60   #define SF_minus1  make_SF(-1,SF_exp_mid+1,bit(SF_mant_len))
61
62
63 // Entpacken eines Short-Float:
64 // SF_decode(obj, zero_statement, sign=,exp=,mant=);
65 // zerlegt ein Short-Float obj.
66 // Ist obj=0.0, wird zero_statement ausgeführt.
67 // Sonst: cl_signean sign = Vorzeichen (0 = +, -1 = -),
68 //        sintL exp = Exponent (vorzeichenbehaftet),
69 //        uintL mant = Mantisse (>= 2^SF_mant_len, < 2^(SF_mant_len+1))
70 inline uintL SF_uexp (const cl_SF& x)
71 {
72         return (x.word >> SF_exp_shift) & (bit(SF_exp_len)-1);
73 }
74 inline cl_signean SF_sign (const cl_SF& x)
75 {
76         return ((cl_sint)x.word << (cl_pointer_size-1 - SF_sign_shift)) >> (cl_pointer_size-1);
77 }
78 inline uintL SF_mant (const cl_SF& x)
79 {
80         return
81                #if SF_mant_hiddenbit
82                bit(SF_mant_len) |
83                #endif
84                ((uintL)(x.word >> SF_mant_shift) & (bit(SF_mant_len)-1));
85 }
86 #define SF_decode(_x, zero_statement, sign_zuweisung,exp_zuweisung,mant_zuweisung)  \
87   { var uintL uexp = SF_uexp(_x);                                       \
88     if (uexp==0)                                                        \
89       { zero_statement } /* e=0 -> Zahl 0.0 */                          \
90       else                                                              \
91       { exp_zuweisung (sintL)(uexp - SF_exp_mid);       /* Exponent */  \
92         unused (sign_zuweisung SF_sign(_x));            /* Vorzeichen */\
93         mant_zuweisung SF_mant(_x);                     /* Mantisse */  \
94   }   }
95
96 // Einpacken eines Short-Float:
97 // encode_SF(sign,exp,mant)
98 // liefert ein Short-Float.
99 // > cl_signean sign: Vorzeichen, 0 für +, -1 für negativ.
100 // > sintL exp: Exponent
101 // > uintL mant: Mantisse, sollte >= 2^SF_mant_len und < 2^(SF_mant_len+1) sein.
102 // < object ergebnis: ein Short-Float
103 // Der Exponent wird auf Überlauf/Unterlauf getestet.
104 inline const cl_SF encode_SF (cl_signean sign, sintL exp, uintL mant)
105 {
106         if (exp < (sintL)(SF_exp_low-SF_exp_mid))
107           { if (underflow_allowed())
108               { throw floating_point_underflow_exception(); }
109               else
110               { return SF_0; }
111           }
112         else
113         if (exp > (sintL)(SF_exp_high-SF_exp_mid))
114           { throw floating_point_overflow_exception(); }
115         else
116         return make_SF(sign, exp+SF_exp_mid, mant);
117 }
118
119
120 // Liefert zu einem Short-Float x : (futruncate x), ein SF.
121 // x wird von der 0 weg zur nächsten ganzen Zahl gerundet.
122 extern const cl_SF futruncate (const cl_SF& x);
123
124 // SF_to_I(x) wandelt ein Short-Float x, das eine ganze Zahl darstellt,
125 // in ein Integer um.
126 extern const cl_I cl_SF_to_I (const cl_SF& x);
127
128 // cl_I_to_SF(x) wandelt ein Integer x in ein Short-Float um und rundet dabei.
129 extern const cl_SF cl_I_to_SF (const cl_I& x);
130
131 // cl_RA_to_SF(x) wandelt eine rationale Zahl x in ein Short-Float um
132 // und rundet dabei.
133 extern const cl_SF cl_RA_to_SF (const cl_RA& x);
134
135 }  // namespace cln
136
137 #endif /* _CL_SF_H */