]> www.ginac.de Git - cln.git/blob - src/float/lfloat/elem/cl_LF_scale_I.cc
Fix scale_float for large factors on x86.
[cln.git] / src / float / lfloat / elem / cl_LF_scale_I.cc
1 // scale_float().
2
3 // General includes.
4 #include "base/cl_sysdep.h"
5
6 // Specification.
7 #include "cln/lfloat.h"
8
9
10 // Implementation.
11
12 #include "float/lfloat/cl_LF.h"
13 #include "float/lfloat/cl_LF_impl.h"
14 #include "float/cl_F.h"
15 #include "integer/cl_I.h"
16
17 namespace cln {
18
19 const cl_LF scale_float (const cl_LF& x, const cl_I& delta)
20 {
21   // Methode:
22   // delta=0 -> x als Ergebnis
23   // x=0.0 -> x als Ergebnis
24   // delta muß ein Integer betragsmäßig <= LF_exp_high-LF_exp_low sein.
25   // Neues LF mit um delta vergrößertem Exponenten bilden.
26       if (eq(delta,0)) { return x; } // delta=0 -> x als Ergebnis
27       var uintE uexp = TheLfloat(x)->expo;
28       if (uexp==0) { return x; }
29       var uintE udelta;
30       // |delta| muß <= LF_exp_high-LF_exp_low < 2^intEsize sein.
31         if (fixnump(delta)) {
32                 // Fixnum
33                 var sintV sdelta = FN_to_V(delta);
34                 if (sdelta >= 0)
35                         { udelta = sdelta; goto pos; }
36                 else
37                         { udelta = sdelta; goto neg; }
38         } else {
39                 // Bignum
40                 var cl_heap_bignum* bn = TheBignum(delta);
41                 if ((sintD)mspref(arrayMSDptr(bn->data,bn->length),0) >= 0) {
42                         // delta >= 0
43                         try {
44                                 udelta = cl_I_to_UE(delta);
45                                 goto pos;
46                         } catch (const runtime_exception&) {
47                                 goto overflow;
48                         }
49                 } else {
50                         // delta < 0
51                         try {
52                                 udelta = cl_I_to_E(delta);
53                                 goto neg;
54                         } catch (const runtime_exception&) {
55                                 goto underflow;
56                         }
57                 }
58         }
59
60       pos: // udelta = delta >=0
61         if (   ((uexp = uexp+udelta) < udelta) // Exponent-Überlauf?
62             || (uexp > LF_exp_high) // oder Exponent zu groß?
63            )
64           overflow:
65           { throw floating_point_overflow_exception(); }
66         goto ok;
67
68       neg: // delta <0, udelta = 2^intEsize+delta
69         if (   ((uexp = uexp+udelta) >= udelta) // oder Exponent-Unterlauf?
70             || (uexp < LF_exp_low) // oder Exponent zu klein?
71            )
72           underflow:
73           { throw floating_point_underflow_exception(); }
74         goto ok;
75
76       ok:
77         var uintC len = TheLfloat(x)->len;
78         return encode_LFu(TheLfloat(x)->sign,uexp,arrayMSDptr(TheLfloat(x)->data,len),len);
79 }
80
81 }  // namespace cln