forked from cgay/shootout
-
Notifications
You must be signed in to change notification settings - Fork 2
/
pidigits.dylan
executable file
·77 lines (61 loc) · 2.07 KB
/
pidigits.dylan
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
module: pidigits
/*
* Based on Christopher Neufeld's <shootout0000@cneufeld.ca>
* SBCL implementation.
*/
define constant $digits-per-line = 10;
define function compose-val (a1, a2)
vector(
( a1[0] * a2[0] ) + ( a1[1] * a2[2] ),
( a1[0] * a2[1] ) + ( a1[1] * a2[3] ),
( a1[2] * a2[0] ) + ( a1[3] * a2[2] ),
( a1[2] * a2[1] ) + ( a1[3] * a2[3] ) );
end function compose-val;
define function compute-pi ( *stop-digits*)
let z = vector(#e1, #e0, #e0, #e1);
let $curstate = vector( #e0, #e2, #e0, #e1 );
local method extract-digit (state, x :: <integer> ) => result :: <extended-integer>;
let numerator :: <extended-integer> = x * state[0] + state[1];
let denominator :: <extended-integer> = x * state[2] + state[3];
floor/ ( numerator, denominator );
end method extract-digit;
local method safe?( val, n ) => result :: <boolean>;
n = extract-digit(val, 4);
end method safe?;
local method produce (val, n)
compose-val( vector( 10, (n * -10), 0, 1 ), val );
end method produce;
local method next-digit (val)
extract-digit( val, 3 );
end method next-digit;
local method consume (val, val-prime)
compose-val(val, val-prime);
end method consume;
local method next-state ()
$curstate[0] := ( $curstate[0] + 1 );
$curstate[1] := ( $curstate[1] + 4 );
$curstate[3] := ( $curstate[3] + 2 );
$curstate;
end method next-state;
let digits-out = 0;
while ( digits-out < *stop-digits* )
let y = next-digit( z );
if ( safe?(z, y) )
begin
format-out( "%d", y );
digits-out := digits-out + 1;
if ( zero?( modulo( digits-out, $digits-per-line ) ) )
format-out( "\t:%d\n", digits-out );
end if;
z := produce( z, y );
end;
else
z := consume( z, next-state() );
end if;
end while;
end function compute-pi;
begin
let *stop-digits* =
string-to-integer( element( application-arguments(), 0, default: "300"));
compute-pi( *stop-digits* );
end;