1 #if !defined HAVE_FRACTIONAL_BASE_NUMBER_H__
2 #define      HAVE_FRACTIONAL_BASE_NUMBER_H__
3 // This file is part of the FXT library.
4 // Copyright (C) 2021 Joerg Arndt
5 // License: GNU General Public License version 3 or later,
6 // see the file COPYING.txt in the main directory.
7 
8 
9 #include "fxttypes.h"
10 
11 #include <iostream>
12 
13 #define FRACTIONAL_BASE_NUMBER_FIXARRAYS
14 
15 class fractional_base_number
16 // Numbers with fractional base b_num / b_den.
17 // Special case b_den == 1 gives the usual base - b_num numbers.
18 // Must have b_num >= 2 and 1 <= b_den < b_num.
19 {
20 public:
21     static constexpr ulong enough = 256;  // max. number of digits
22 private:
23 #ifdef FRACTIONAL_BASE_NUMBER_FIXARRAYS
24     ulong D[enough];
25 #else
26     ulong * D { nullptr };
27 #endif
28 
29     ulong num_dig;  // current number of digits, set to 0 for the number zero
30     const ulong b_num = 3;  // base: numerator
31     const ulong b_den = 2;  // base: denominator
32     const ulong num_dig_max;  // max for num_dig
33 
34 
35 public:
fractional_base_number(ulong b_num_,ulong b_den_,ulong num_dig_max_)36     fractional_base_number( ulong b_num_, ulong b_den_, ulong num_dig_max_)
37         : b_num(b_num_), b_den(b_den_), num_dig_max(num_dig_max_)
38     {
39 #ifdef FRACTIONAL_BASE_NUMBER_FIXARRAYS
40 #else
41         D = new ulong[num_dig_max];
42 #endif
43         first();
44     }
45 
~fractional_base_number()46     ~fractional_base_number()
47     {
48 #ifdef FRACTIONAL_BASE_NUMBER_FIXARRAYS
49 #else
50         delete [] D;
51 #endif
52     }
53 
first()54     ulong first()
55     {
56         for (ulong j=0; j <= num_dig_max; ++j)  D[j] = 0;
57         num_dig = 0;
58         return num_dig;  // zero has no digits
59     }
60 
data()61     const ulong * data()  const  { return D; }
62 
63 private:
64 //    __attribute__((always_inline))
incr_at(ulong j,ulong cy)65     ulong incr_at( ulong j, ulong cy )
66     // return carry
67     {
68         const ulong di = D[j] + cy;
69         if ( di < b_num )
70         {
71             D[ j ] = di;
72             return 0;
73         }
74         else
75         {
76             D[ j ] = di - b_num;
77             return  b_den;
78         }
79     }
80 
81 public:
next()82     ulong next()
83     {
84         ulong j = 0;
85         ulong cy = 1;
86         do
87         {
88             cy = incr_at(j, cy);
89             j += 1;
90         }
91         while ( cy != 0 );
92 
93         if ( j > num_dig ) num_dig = j;  // increment num_dig
94 
95         if ( num_dig > num_dig_max )  return 0;
96 
97         return num_dig;
98     }
99 
print_as_array()100     void print_as_array()  const
101     // unit digit first
102     // the number zero gives no output
103     {
104         for (ulong j=0; j<num_dig; ++j)
105         {
106             std::cout << D[j];
107             if ( b_num > 10 )  std::cout << ',';
108         }
109 //        std::cout << "\n";
110     }
111 
print_as_number()112     void print_as_number()  const
113     // unit digit last
114     // the number zero gives no output
115     {
116         ulong j = num_dig;
117         while ( j != 0 )
118         {
119             j -= 1;
120             std::cout << D[j];
121             if ( b_num > 10 )  std::cout << ',';
122         }
123 //        std::cout << "\n";
124     }
125 };
126 // -------------------------
127 
128 #endif  // !defined HAVE_FRACTIONAL_BASE_NUMBER_H__
129