/** * The Computer Language Benchmarks Game * http://shootout.alioth.debian.org/ * * Port of the Java port that uses native GMP to use native GMP with C# * * contributed by Mike Pall * java port by Stefan Krause */ using System; using System.Text; using System.Runtime.InteropServices; public class pidigits { GmpInteger q = new GmpInteger(), r = new GmpInteger(), s = new GmpInteger(), t = new GmpInteger(); GmpInteger u = new GmpInteger(), v = new GmpInteger(), w = new GmpInteger(); int i; StringBuilder strBuf = new StringBuilder (40); int n; pidigits (int n) { this.n=n; } private void compose_r(int bq, int br, int bs, int bt) { u.mul(r, bs); r.mul(r, bq); v.mul(t, br); r.add(r, v); t.mul(t, bt); t.add(t, u); s.mul(s, bt); u.mul(q, bs); s.add(s, u); q.mul(q, bq); } /* Compose matrix with numbers on the left. */ private void compose_l(int bq, int br, int bs, int bt) { r.mul(r, bt); u.mul(q, br); r.add(r, u); u.mul(t, bs); t.mul(t, bt); v.mul(s, br); t.add(t, v); s.mul(s, bq); s.add(s, u); q.mul(q, bq); } /* Extract one digit. */ private int extract(int j) { u.mul(q, j); u.add(u, r); v.mul(s, j); v.add(v, t); w.div(u, v); return w.intValue(); } /* Print one digit. Returns 1 for the last digit. */ private bool prdigit(int y) { strBuf.Append(y); if (++i % 10 == 0 || i == n) { if (i%10!=0) for (int j=10-(i%10);j>0;j--) { strBuf.Append(" "); } strBuf.Append("\t:"); strBuf.Append(i); Console.WriteLine(strBuf); strBuf = new StringBuilder(40); } return i == n; } /* Generate successive digits of PI. */ void Run() { int k = 1; i = 0; q.set(1); r.set(0); s.set(0); t.set(1); for (;;) { int y = extract(3); if (y == extract(4)) { if (prdigit(y)) return; compose_r(10, -10*y, 0, 1); } else { compose_l(k, 4*k+2, 0, 2*k+1); k++; } } } public static void Main(String[] args) { pidigits m = new pidigits(Int32.Parse (args[0])); m.Run(); } } [StructLayout (LayoutKind.Sequential)] struct mpz_t { int _mp_alloc; int _mp_size; IntPtr ptr; } class GmpInteger { // Public methods public GmpInteger() { mpz_init(ref pointer); } public GmpInteger(int value) { mpz_set_si(ref pointer, value); } public void set(int value) { mpz_set_si(ref pointer, value); } public void mul(GmpInteger src, int val) { mpz_mul_si(ref pointer, ref src.pointer, val); } public void add(GmpInteger op1, GmpInteger op2) { mpz_add(ref pointer, ref op1.pointer, ref op2.pointer); } public void div(GmpInteger op1, GmpInteger op2) { mpz_tdiv_q(ref pointer, ref op1.pointer, ref op2.pointer); } public int intValue() { return mpz_get_si(ref pointer); } public double doubleValue() { return mpz_get_d(ref pointer); } // Non public stuff mpz_t pointer; protected void finalize() { //mpz_clear(pointer); } [DllImport ("gmp", EntryPoint="__gmpz_init")] extern static void mpz_init(ref mpz_t value); [DllImport ("gmp", EntryPoint="__gmpz_clear")] extern static void mpz_clear(ref mpz_t src); [DllImport ("gmp", EntryPoint="__gmpz_mul_si")] extern static void mpz_mul_si(ref mpz_t dest, ref mpz_t src, int val); [DllImport ("gmp", EntryPoint="__gmpz_add")] extern static void mpz_add(ref mpz_t dest, ref mpz_t src, ref mpz_t src2); [DllImport ("gmp", EntryPoint="__gmpz_tdiv_q")] extern static void mpz_tdiv_q(ref mpz_t dest, ref mpz_t src, ref mpz_t src2); [DllImport ("gmp", EntryPoint="__gmpz_set_si")] extern static void mpz_set_si(ref mpz_t src, int value); [DllImport ("gmp", EntryPoint="__gmpz_get_si")] extern static int mpz_get_si(ref mpz_t src); [DllImport ("gmp", EntryPoint="__gmpz_get_d")] extern static double mpz_get_d(ref mpz_t src); }