@@ -37,21 +37,34 @@ class simple_continued_fraction {
37
37
public:
38
38
typedef Z int_type;
39
39
40
- simple_continued_fraction (Real x) {
40
+ simple_continued_fraction (std::vector<Z> data) : b_{std::move (data)} {
41
+ const size_t size_ = b_.size ();
42
+ if (size_ == 0 ) {
43
+ throw std::length_error (" Array of coefficients is empty." );
44
+ }
45
+
46
+ for (size_t i = 1 ; i < size_; ++i) {
47
+ if (b_[i] <= 0 ) {
48
+ std::ostringstream oss;
49
+ oss << " Found a negative partial denominator: b[" << i << " ] = " << b_[i] << " ." ;
50
+ throw std::domain_error (oss.str ());
51
+ }
52
+ }
53
+
54
+ canonicalize ();
55
+ }
56
+
57
+ simple_continued_fraction (Real x) : b_{} {
41
58
using std::floor ;
42
59
using std::abs ;
43
60
using std::sqrt ;
44
61
using std::isfinite;
45
- const Real orig_x = x;
46
62
if (!isfinite (x)) {
47
63
throw std::domain_error (" Cannot convert non-finites into continued fractions." );
48
64
}
49
65
50
- constexpr int p = std::numeric_limits<Real>::max_digits10;
51
- if constexpr (p == 2147483647 ) {
52
- precision_ = orig_x.backend ().precision ();
53
- } else {
54
- precision_ = p;
66
+ if constexpr (std_precision == 2147483647 ) {
67
+ precision_ = x.backend ().precision ();
55
68
}
56
69
57
70
b_.reserve (50 );
@@ -61,6 +74,8 @@ class simple_continued_fraction {
61
74
b_.shrink_to_fit ();
62
75
return ;
63
76
}
77
+
78
+ const Real orig_x = x;
64
79
x = 1 /(x-bj);
65
80
Real f = bj;
66
81
if (bj == 0 ) {
@@ -87,14 +102,7 @@ class simple_continued_fraction {
87
102
D = 1 /D;
88
103
f *= (C*D);
89
104
}
90
- // Deal with non-uniqueness of continued fractions: [a0; a1, ..., an, 1] = a0; a1, ..., an + 1].
91
- // The shorter representation is considered the canonical representation,
92
- // so if we compute a non-canonical representation, change it to canonical:
93
- if (b_.size () > 2 && b_.back () == 1 ) {
94
- b_.pop_back ();
95
- b_.back () += 1 ;
96
- }
97
- b_.shrink_to_fit ();
105
+ canonicalize ();
98
106
99
107
const size_t size_ = b_.size ();
100
108
for (size_t i = 1 ; i < size_; ++i) {
@@ -163,9 +171,22 @@ class simple_continued_fraction {
163
171
template <typename T, typename Z2>
164
172
friend std::ostream& operator <<(std::ostream& out, simple_continued_fraction<T, Z2>& scf);
165
173
private:
166
- std::vector<Z> b_{};
174
+ static constexpr int std_precision = std::numeric_limits<Real>::max_digits10;
175
+
176
+ void canonicalize () {
177
+ // Deal with non-uniqueness of continued fractions: [a0; a1, ..., an, 1] = a0; a1, ..., an + 1].
178
+ // The shorter representation is considered the canonical representation,
179
+ // so if we compute a non-canonical representation, change it to canonical:
180
+ if (b_.size () > 2 && b_.back () == 1 ) {
181
+ b_.pop_back ();
182
+ b_.back () += 1 ;
183
+ }
184
+ b_.shrink_to_fit ();
185
+ }
186
+
187
+ std::vector<Z> b_;
167
188
168
- int precision_{};
189
+ int precision_{std_precision };
169
190
};
170
191
171
192
@@ -189,7 +210,7 @@ std::ostream& operator<<(std::ostream& out, simple_continued_fraction<Real, Z2>&
189
210
template <typename Real, typename Z = std::int64_t >
190
211
inline auto simple_continued_fraction_coefficients (Real x)
191
212
{
192
- auto temp = simple_continued_fraction (x);
213
+ auto temp = simple_continued_fraction<Real, Z> (x);
193
214
return temp.get_data ();
194
215
}
195
216
0 commit comments