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