Continued fraction/Arithmetic/G(matrix ng, continued fraction n1, continued fraction n2): Difference between revisions

Content added Content deleted
Line 3,507: Line 3,507:
-1 -3 -5 -1 -2 -1 -26 -3
-1 -3 -5 -1 -2 -1 -26 -3
-1 -3 -5 -1 -2 -1 -26 -3 </pre>
-1 -3 -5 -1 -2 -1 -26 -3 </pre>

=={{header|ObjectIcon}}==
{{trans|Scheme}}

Where the Scheme uses thunks, the Object Icon uses co-expressions.

<syntaxhighlight lang="ObjectIcon">
# -*- ObjectIcon -*-

import io

global golden_ratio
global silver_ratio
global sqrt2
global frac_13_11
global frac_22_7
global one, two, three, four

procedure r2cf (n, d)
return CF (create r2cf_generate (n, d))
end

procedure i2cf (i)
return CF (create r2cf_generate (i, 1))
end

procedure cf_add (x, y)
return NG8(0, 1, 1, 0, 0, 0, 0, 1).apply(x, y)
end

procedure cf_sub (x, y)
return NG8(0, 1, -1, 0, 0, 0, 0, 1).apply(x, y)
end

procedure cf_mul (x, y)
return NG8(1, 0, 0, 0, 0, 0, 0, 1).apply(x, y)
end

procedure cf_div (x, y)
return NG8(0, 1, 0, 0, 0, 0, 1, 0).apply(x, y)
end

procedure main ()
initial {
initialize_global_CF ()
}

show ("golden ratio", golden_ratio, "(1 + sqrt(5))/2")
show ("silver ratio", silver_ratio, "(1 + sqrt(2))")
show ("sqrt(2)", sqrt2, "silver ratio minus 1")
show ("13/11", frac_13_11)
show ("22/7", frac_22_7, "approximately pi")
show ("1", one)
show ("2", two)
show ("3", three)
show ("4", four)

show ("(1 + 1/sqrt(2))/2",
NG8(0, 1, 0, 0, 0, 0, 2, 0).apply(silver_ratio, sqrt2),
"method 1")
show ("(1 + 1/sqrt(2))/2",
NG8(1, 0, 0, 1, 0, 0, 0, 8).apply(silver_ratio, silver_ratio),
"method 2")
show ("(1 + 1/sqrt(2))/2",
cf_mul (cf_add (one, (cf_div (one, sqrt2))), r2cf (1, 2)),
"method 3")

show ("sqrt(2) + sqrt(2)", cf_add (sqrt2, sqrt2));
show ("sqrt(2) - sqrt(2)", cf_sub (sqrt2, sqrt2));
show ("sqrt(2) * sqrt(2)", cf_mul (sqrt2, sqrt2));
show ("sqrt(2) / sqrt(2)", cf_div (sqrt2, sqrt2));
end

procedure initialize_global_CF ()
golden_ratio := CF (create generate_constant (1))
silver_ratio := CF (create generate_constant (2))
frac_13_11 := r2cf (13, 11)
frac_22_7 := r2cf (22, 7)
one := i2cf (1)
two := i2cf (2)
three := i2cf (3)
four := i2cf (4)
sqrt2 := cf_sub (silver_ratio, one)
return
end

procedure show (expression, cf, note)
io.writes (right (expression, 19), " => ")
if /note then
io.write (cf.to_string())
else
io.write (left (cf.to_string(), 48), note)
return
end

class CF () # Continued fraction.

private terminated # Are there no more terms to memoize?
private memo # Memoized terms.
private term_gen # A co-expression to generate more terms.

public static default_max_terms

public new (gen)
terminated := &no
memo := []
term_gen := gen
return
end

public get_term (i) # Get the ith term (or fail if there is none).
local j, term

if *memo <= i then {
if \terminated then
fail
else
{
every j := *memo to i do {
if \ (term := @term_gen) then
put (memo, term)
else {
terminated := &yes
fail
}
}
}
}
return memo[i + 1]
end

public generate () # Generate the terms, with &null as "infinity".
local i, term

i := 0
while term := get_term (i) do
{
suspend term
i +:= 1
}
repeat suspend &null
end

public to_coexpression () # Co-expression that generates terms.
return create generate ()
end

public to_string (max_terms) # Make a human-readable string.
local s, i, done, term

/max_terms := (\default_max_terms | 20)

s := "["
i := 0
done := &no
while /done do
{
if not (term := get_term (i)) then
{
s ||:= "]"
done := &yes
}
else if i = max_terms then
{
s ||:= ",...]"
done := &yes
}
else
{
s ||:= sep_str (i) || term
i +:= 1
}
}
return s
end

private sep_str (i) # A helper procedure for to_string.
return (if i = 0 then "" else if i = 1 then ";" else ",")
end

end # end class CF

class NG8 () # A bihomographic function.

private na12, na1, na2, na
private nb12, nb1, nb2, nb

public static practically_infinite_number
public static much_too_big_number

public new (a12, a1, a2, a, b12, b1, b2, b)
initial {
practically_infinite_number := 2^64
much_too_big_number := 2^512
}
na12 := a12
na1 := a1
na2 := a2
na := a
nb12 := b12
nb1 := b1
nb2 := b2
nb := b
return
end

public apply (x, y) # Make a CF that applies the operation.
return CF (create generate (x, y))
end

public generate (x, y) # Apply the operation to generate terms.
local xsource, ysource
local a12, a1, a2, a
local b12, b1, b2, b
local r12, r1, r2, r
local n1, n2, n
local absorb_term_from
local term
local new_a12, new_a1, new_a2, new_a
local new_b12, new_b1, new_b2, new_b

xsource := make_source (x)
ysource := make_source (y)

a12 := na12; a1 := na1; a2 := na2; a := na
b12 := nb12; b1 := nb1; b2 := nb2; b := nb

repeat
{
absorb_term_from := &null
if b12 = b1 = b2 = b = 0 then
suspend &null # "Infinity".
else if b2 = b = 0 then
absorb_term_from := 'x'
else if b2 = 0 | b = 0 then
absorb_term_from := 'y'
else if b1 = 0 then
absorb_term_from := 'x'
else if b12 ~= 0 & term := (a12/b12 = a1/b1 = a2/b2 = a/b) then
{
suspend infinitized (term)
r12 := a12 % b12
r1 := a1 % b1
r2 := a2 % b2
r := a % b
a12 := b12; a1 := b1; a2 := b2; a := b
b12 := r12; b1 := r1; b2 := r2; b := r
}
else
{
# Put numerators over a common denominator.
n1 := a1 * b2 * b
n2 := a2 * b1 * b
n := a * b1 * b2
if abs (n1 - n) > abs (n2 - n) then
absorb_term_from := 'x'
else
absorb_term_from := 'y'
}

if \absorb_term_from === 'x' then {
term := @xsource
new_a2 := a12; new_a := a1
new_b2 := b12; new_b := b1
if \term then
{
new_a12 := a2 + (a12 * term)
new_a1 := a + (a1 * term)
new_b12 := b2 + (b12 * term)
new_b1 := b + (b1 * term)
if too_big (new_a12 | new_a1 | new_a2 | new_a |
new_b12 | new_b1 | new_b2 | new_b) then
{
# All further terms are forced to "infinity".
xsource := make_source (&null)
new_a12 := a12; new_a1 := a1
new_b12 := b12; new_b1 := b1
}
}
a12 := new_a12; a1 := new_a1; a2 := new_a2; a := new_a
b12 := new_b12; b1 := new_b1; b2 := new_b2; b := new_b
}
else if \absorb_term_from === 'y' then
{
term := @ysource
new_a1 := a12; new_a := a2
new_b1 := b12; new_b := b2
if \term then
{
new_a12 := a1 + (a12 * term)
new_a2 := a + (a2 * term)
new_b12 := b1 + (b12 * term)
new_b2 := b + (b2 * term)
if too_big (new_a12 | new_a1 | new_a2 | new_a |
new_b12 | new_b1 | new_b2 | new_b) then
{
# All further terms are forced to "infinity".
ysource := make_source (&null)
new_a12 := a12; new_a2 := a2
new_b12 := b12; new_b2 := b2
}
}
a12 := new_a12; a1 := new_a1; a2 := new_a2; a := new_a
b12 := new_b12; b1 := new_b1; b2 := new_b2; b := new_b
}
}
end

private make_source (cf)
local source

if /cf then
# Generate "infinity" terms.
source := create generate_constant (&null)
else if type(cf) == "co-expression" then
# Already a co-expression.
source := cf
else
# Use a continued fraction as a co-expression.
source := cf.to_coexpression ()
return source
end

private infinitized (term)
if abs (term) >= abs (practically_infinite_number) then
term := &null
return term
end

private too_big (num)
if abs (num) < abs (much_too_big_number) then fail
return num
end

end # end class NG8

procedure generate_constant (constant)
repeat suspend constant
end

procedure r2cf_generate (n, d)
local remainder
repeat
{
if d = 0 then
suspend &null
else
{
suspend (n / d)
remainder := n % d
n := d
d := remainder
}
}
end
</syntaxhighlight>

{{out}}
<pre>$ oiscript bivariate_continued_fraction_task_OI.icn
golden ratio => [1;1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,...] (1 + sqrt(5))/2
silver ratio => [2;2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,...] (1 + sqrt(2))
sqrt(2) => [1;2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,...] silver ratio minus 1
13/11 => [1;5,2]
22/7 => [3;7] approximately pi
1 => [1]
2 => [2]
3 => [3]
4 => [4]
(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,...] method 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,...] method 2
(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,...] method 3
sqrt(2) + sqrt(2) => [2;1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,...]
sqrt(2) - sqrt(2) => [0]
sqrt(2) * sqrt(2) => [2]
sqrt(2) / sqrt(2) => [1]
</pre>


=={{header|Phix}}==
=={{header|Phix}}==