Continued fraction/Arithmetic/G(matrix ng, continued fraction n): Difference between revisions
Content added Content deleted
Line 3,156: | Line 3,156: | ||
SBCL might be the most likely CL implementation to be installed: |
SBCL might be the most likely CL implementation to be installed: |
||
<pre>$ sbcl --script univariate-continued-fraction-task.lisp |
<pre>$ sbcl --script univariate-continued-fraction-task.lisp |
||
13/11 => [1;5,2] |
|||
22/7 => [3;7] |
|||
sqrt(2) => [1;2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,...] |
|||
13/11 + 1/2 => [1;1,2,7] |
|||
22/7 + 1/2 => [3;1,1,1,4] |
|||
(22/7)/4 => [0;1,3,1,2] |
|||
sqrt(2)/2 => [0;1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,...] |
|||
1/sqrt(2) => [0;1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,...] |
|||
(2 + sqrt(2))/4 => [0;1,5,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,...] |
|||
(1 + 1/sqrt(2))/2 => [0;1,5,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,...] |
|||
sqrt(2)/4 + 1/2 => [0;1,5,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,...] |
|||
(sqrt(2)/2)/2 + 1/2 => [0;1,5,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,...] |
|||
(1/sqrt(2))/2 + 1/2 => [0;1,5,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,...]</pre> |
|||
=={{header|D}}== |
|||
{{trans|ATS}} |
|||
{{works with|Digital Mars D|2.099.1}} |
|||
{{works with|GCC|12.2.1}} |
|||
This implementation memoizes terms of a continued fraction. It leaks memory, but D provides a garbage collector. |
|||
<syntaxhighlight lang="D"> |
|||
import std.conv; |
|||
import std.stdio; |
|||
alias index_t = uint; // The type for indexing terms of a continued |
|||
// fraction. |
|||
alias integer = long; // The type for terms of a continued fraction. |
|||
class cf_t // A continued fraction, with memoization of its terms. |
|||
{ |
|||
protected bool terminated; // Are there more terms to be memoized? |
|||
protected index_t m; // How many terms are memoized so far? |
|||
private integer[] memo; // Memoized terms. |
|||
public index_t maxTerms = 20; // Maximum number of terms in the |
|||
// string representation. |
|||
this () |
|||
{ |
|||
terminated = false; |
|||
m = 0; |
|||
memo.length = 8; |
|||
} |
|||
protected void generate (ref bool termExists, ref integer term) |
|||
{ |
|||
// Return terms for zero. To get different terms, override this |
|||
// method. (I am used to using a closure or similar for the |
|||
// generator, and not having to derive a new continued fraction |
|||
// type, to have a new kind of generator. However, I am trying to |
|||
// do what is more natural within the programming language.) |
|||
termExists = (m == 0); |
|||
term = 0; |
|||
} |
|||
public void getAt (index_t i, ref bool termExists, ref integer term) |
|||
{ |
|||
void memoizeMoreTerms (index_t needed) |
|||
{ |
|||
while (m != needed && !terminated) |
|||
{ |
|||
bool termExists; |
|||
integer term; |
|||
generate (termExists, term); |
|||
if (termExists) |
|||
{ |
|||
memo[m] = term; |
|||
m += 1; |
|||
} |
|||
else |
|||
terminated = true; |
|||
} |
|||
} |
|||
void update (index_t needed) |
|||
{ |
|||
// If necessary, memoize more terms, perhaps increasing the |
|||
// space in which to store them. |
|||
if (!terminated && m < needed) |
|||
{ |
|||
if (needed <= memo.length) |
|||
{ |
|||
// Increase the space to twice what might be needed |
|||
// right now. |
|||
memo.length = 2 * needed; |
|||
} |
|||
memoizeMoreTerms (needed); |
|||
} |
|||
} |
|||
update (i + 1); |
|||
termExists = (i < m); |
|||
if (termExists) |
|||
term = memo[i]; |
|||
} |
|||
public override string toString () |
|||
{ |
|||
string s = "["; |
|||
int sep = 0; |
|||
index_t i = 0; |
|||
bool done = false; |
|||
while (!done) |
|||
{ |
|||
if (i == maxTerms) |
|||
{ |
|||
s ~= ",...]"; |
|||
done = true; |
|||
} |
|||
else |
|||
{ |
|||
bool termExists; |
|||
integer term; |
|||
getAt (i, termExists, term); |
|||
if (termExists) |
|||
{ |
|||
final switch (sep) |
|||
{ |
|||
case 0 : |
|||
sep = 1; |
|||
break; |
|||
case 1 : |
|||
s ~= ";"; |
|||
sep = 2; |
|||
break; |
|||
case 2 : |
|||
s ~= ","; |
|||
break; |
|||
} |
|||
s ~= to!string (term); |
|||
i += 1; |
|||
} |
|||
else |
|||
{ |
|||
s ~= "]"; |
|||
done = true; |
|||
} |
|||
} |
|||
} |
|||
return s; |
|||
} |
|||
} |
|||
class cfSqrt2_t : cf_t // A continued fraction for sqrt(2). |
|||
{ |
|||
override final void generate (ref bool termExists, ref integer term) |
|||
{ |
|||
termExists = true; |
|||
term = (m == 0 ? 1 : 2); |
|||
} |
|||
} |
|||
class cfRational : cf_t // A continued fraction for a rational number. |
|||
{ |
|||
private integer n; // Numerator. |
|||
private integer d; // Denominator. |
|||
this (integer numerator, integer denominator) |
|||
{ |
|||
assert (denominator != 0); |
|||
n = numerator; |
|||
d = denominator; |
|||
} |
|||
override void generate (ref bool termExists, ref integer term) |
|||
{ |
|||
termExists = (d != 0); |
|||
if (termExists) |
|||
{ |
|||
auto q = n / d; |
|||
auto r = n % d; |
|||
n = d; |
|||
d = r; |
|||
term = q; |
|||
} |
|||
} |
|||
} |
|||
class hfunc_t // A homographic function. |
|||
{ |
|||
public integer a1; |
|||
public integer a; |
|||
public integer b1; |
|||
public integer b; |
|||
this (integer a1, integer a, integer b1, integer b) |
|||
{ |
|||
this.a1 = a1; |
|||
this.a = a; |
|||
this.b1 = b1; |
|||
this.b = b; |
|||
} |
|||
} |
|||
class cfHfunc_t : cf_t // A continued fraction that is a homographic |
|||
// function of some other continued fraction. |
|||
{ |
|||
private integer a1; |
|||
private integer a; |
|||
private integer b1; |
|||
private integer b; |
|||
private cf_t gen; |
|||
private index_t index; |
|||
this (hfunc_t hfunc, cf_t gen) |
|||
{ |
|||
a1 = hfunc.a1; |
|||
a = hfunc.a; |
|||
b1 = hfunc.b1; |
|||
b = hfunc.b; |
|||
this.gen = gen; |
|||
index = 0; |
|||
} |
|||
override void generate (ref bool termExists, ref integer term) |
|||
{ |
|||
bool done = false; |
|||
while (!done) |
|||
{ |
|||
if (b1 == 0 && b == 0) |
|||
{ |
|||
termExists = false; |
|||
done = true; |
|||
} |
|||
else if (b1 != 0 && b != 0) |
|||
{ |
|||
auto q1 = a1 / b1; |
|||
auto q = a / b; |
|||
if (q1 == q) |
|||
{ |
|||
const a1_ = a1; |
|||
const a_ = a; |
|||
const b1_ = b1; |
|||
const b_ = b; |
|||
a1 = b1_; |
|||
a = b_; |
|||
b1 = a1_ - (b1_ * q); |
|||
b = a_ - (b_ * q); |
|||
termExists = true; |
|||
term = q; |
|||
done = true; |
|||
} |
|||
} |
|||
if (!done) |
|||
{ |
|||
gen.getAt (index, termExists, term); |
|||
index += 1; |
|||
if (termExists) |
|||
{ |
|||
const a1_ = a1; |
|||
const a_ = a; |
|||
const b1_ = b1; |
|||
const b_ = b; |
|||
a1 = a_ + (a1_ * term); |
|||
a = a1_; |
|||
b1 = b_ + (b1_ * term); |
|||
b = b1_; |
|||
} |
|||
else |
|||
{ |
|||
a = a1; |
|||
b = b1; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
int |
|||
main (char[][] args) |
|||
{ |
|||
auto hf_cf_add_1_2 = new hfunc_t (2, 1, 0, 2); |
|||
auto hf_cf_div_2 = new hfunc_t (1, 0, 0, 2); |
|||
auto hf_cf_div_4 = new hfunc_t (1, 0, 0, 4); |
|||
auto hf_1_div_cf = new hfunc_t (0, 1, 1, 0); |
|||
auto cf_13_11 = new cfRational (13, 11); |
|||
auto cf_22_7 = new cfRational (22, 7); |
|||
auto cf_sqrt2 = new cfSqrt2_t (); |
|||
auto cf_13_11_add_1_2 = new cfHfunc_t (hf_cf_add_1_2, cf_13_11); |
|||
auto cf_22_7_add_1_2 = new cfHfunc_t (hf_cf_add_1_2, cf_22_7); |
|||
auto cf_22_7_div_4 = new cfHfunc_t (hf_cf_div_4, cf_22_7); |
|||
auto cf_sqrt2_div_2 = new cfHfunc_t (hf_cf_div_2, cf_sqrt2); |
|||
auto cf_1_div_sqrt2 = new cfHfunc_t (hf_1_div_cf, cf_sqrt2); |
|||
auto cf_2_add_sqrt2__div_4 = |
|||
new cfHfunc_t (new hfunc_t (1, 2, 0, 4), cf_sqrt2); |
|||
auto cf_1_add_1_div_sqrt2__div_2 = |
|||
new cfHfunc_t (new hfunc_t (1, 1, 0, 2), cf_1_div_sqrt2); |
|||
auto cf_sqrt2_div_4_add_1_2 = |
|||
new cfHfunc_t (hf_cf_add_1_2, |
|||
new cfHfunc_t (hf_cf_div_4, cf_sqrt2)); |
|||
void show (string expr, cf_t cf) |
|||
{ |
|||
writeln (expr, cf.toString()); |
|||
} |
|||
show ("13/11 => ", cf_13_11); |
|||
show ("22/7 => ", cf_22_7); |
|||
show ("sqrt(2) => ", cf_sqrt2); |
|||
show ("13/11 + 1/2 => ", cf_13_11_add_1_2); |
|||
show ("22/7 + 1/2 => ", cf_22_7_add_1_2); |
|||
show ("(22/7)/4 => ", cf_22_7_div_4); |
|||
show ("sqrt(2)/2 => ", cf_sqrt2_div_2); |
|||
show ("1/sqrt(2) => ", cf_1_div_sqrt2); |
|||
show ("(2 + sqrt(2))/4 => ", cf_2_add_sqrt2__div_4); |
|||
show ("(1 + 1/sqrt(2))/2 => ", cf_1_add_1_div_sqrt2__div_2); |
|||
show ("sqrt(2)/4 + 1/2 => ", cf_sqrt2_div_4_add_1_2); |
|||
show ("(sqrt(2)/2)/2 + 1/2 => ", |
|||
new cfHfunc_t (hf_cf_add_1_2, |
|||
new cfHfunc_t (hf_cf_div_2, |
|||
cf_sqrt2_div_2))); |
|||
// Demonstrate a deeper nesting of anonymous cf_t. |
|||
show ("(1/sqrt(2))/2 + 1/2 => ", |
|||
new cfHfunc_t (hf_cf_add_1_2, |
|||
new cfHfunc_t (hf_cf_div_2, |
|||
new cfHfunc_t (hf_1_div_cf, |
|||
cf_sqrt2)))); |
|||
return 0; |
|||
} |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre>$ dmd -g univariate_continued_fraction_task.d && ./univariate_continued_fraction_task |
|||
13/11 => [1;5,2] |
13/11 => [1;5,2] |
||
22/7 => [3;7] |
22/7 => [3;7] |