Examples of C# source code

Here I have collected some snippets to give a small flavour of the sort of code you will see on this site.  These are taken from non-trivial programs so they might not make complete sense on their own.  For more information or to see the full code, please visit each application's home page.

  1. Performing RSA encryption and decryption
  2. Computing 'true anomaly' for an elliptical orbit
  3. Creating a Mandelbrot set bitmap image

Performing RSA encryption and decryption

(from RSA with BigInts)

This code echoes the famous 1977 RSA Challenge, by generating an RSA key pair based on two large primes (the same primes used in the Challenge) and using this key pair to encrypt and decrypt a message.  The process requires my BigInt class for performing arithmetic on arbitrarily large integers (since the numbers used here are too large for the Pentium's built-in functions).  Notice that, thanks to the C# operators defined by BigInt, the code looks pretty much the same as it would if we were using regular 32-bit integers!

public static void DoDemo()

{

    BigInt p = "398075086424064937397125500550386491199064362342526708406385189575946388957261768583317";

    BigInt q = "472772146107435302536223071973048224632914695302097116459852171130520711256363590397527";

  

    BigInt d, e, n;

    GenerateKeyPair(p, q, out d, out e, out n);

    Console.WriteLine("public key is ({0}, {1})", d, n);

    Console.WriteLine("private key is ({0}, {1})", e, n);

    Console.WriteLine();

  

    //Encode the message "MAGIC SQUEAMISH"

    // using A=01, B=02, Z=26, etc

    BigInt msg = "130107090319172105011309198";

  

    Console.WriteLine("plaintext is {0}", msg);

    BigInt encryptedMsg = BigInt.modpower(msg, d, n);

    Console.WriteLine("plaintext encrypted using public key: {0} -> {1}",

        msg, encryptedMsg);

    Console.WriteLine("cyphertext decrypted using private key: {0} -> {1}",

        encryptedMsg, BigInt.modpower(encryptedMsg, e, n));

}

  

public static void GenerateKeyPair(BigInt p, BigInt q, out BigInt d,

            out BigInt e, out BigInt n)

{

    d = 0; e = 0;

    ushort c = 0, testLimit;

    BigInt r;

    bool done;

   

    n = p * q;

    BigInt phiN = (p-1) * (q-1);

    done = false;

                       

    do

    {

        c++;

        r = phiN.ShortMultiply(c) + 1;

        testLimit = 500;

        for(d = 3; d < testLimit && (r % d != 0); d += 2);

        if(d < testLimit)

        {

            e = r / d;

            if(!( (d % phiN) == (e % phiN) ))

                done = true;

        }

    } while(!done);

}

Computing 'true anomaly' for an elliptical orbit

(from the Hohmann Transfer Orbit demo)

This routine is used by the EllipticalOrbitingBody class to calculate the angle (in radians) between the body and the sun. It solves Kepler’s equation (using Newton-Raphson iteration) to get the body’s ‘eccentric anomaly’, E, which is then used to get the angle.

Kepler’s equation, M = E - e sin(E), relates the ‘mean anomaly’ to the ‘eccentric anomaly’ for a body in an elliptical orbit. The mean anomaly can be thought of as the body’s progress through its orbital period (so if the body has an orbital period of one year and is six months into its orbit then its mean anomaly is π radians; ie half of the total). The eccentric anomaly takes into account Kepler’s law about sweeping out equal areas in equal time (so the body goes faster when closer to the sun). It can be used to compute the exact position in an elliptical orbit of eccentricity e.

Given M and e, we want to solve Kepler’s equation for E. However, the equation is transcendental so we must use non-algebraic techniques to solve it. The demo uses Newton-Raphson iteration. We rewrite the equation as

    f(E) = E - e sin(E) – M

and differentiate with respect to E:

    f’(E) = 1 - e cos(E)

Now to solve f(E) = 0 using Newton-Raphson we iterate

    Xn+1 = Xn - [ f(Xn) / f’(Xn) ]

    i.e. En+1 = En - [ (En - e sin(En) - M) / (1 – e cos(En)) ]

until |En+1 - En| is less than some small amount.

public override double GetTrueAnomaly()

{

    double ecc = eccentricity;                

    double M = base.GetTrueAnomaly(); // the base implementation returns the

                // "mean anomaly", which assumes a circular orbit.

                // The rest of our work involves

                // correcting this to get the true "eccentric" anomaly

    double E, E_new, E_old = M + (ecc / 2);

    const double epsilon = 0.0001;

    double bodyAngle;

  

    //Solve [ 0 = E - e sin(E) - M ] for E using Newton-Raphson: 
    // Xn+1 = Xn - [ f(Xn) / f'(Xn) ]

    // E = Eccentric Anomaly, M = Mean Anomaly

    do

    {

        E_new = E_old - (E_old - ecc * Math.Sin(E_old) - M)

                 / (1 - ecc * Math.Cos(E_old));

        E_old = E_new;

    } while(Math.Abs(E_old - E_new) > epsilon);

       

    E = E_new;

  

    //Solve cos(bodyAngle) = ( cos(E) - e ) / (1 - e cos(E) ) to get the

    // body's angle with the Sun

    bodyAngle = Math.Acos( (Math.Cos(E) - ecc)/(1 - ecc * Math.Cos(E)) );

  

    // Arccos returns a value between 0 and π, but when M > π (ie

    // past halfway point) we

    // take (2π - angle) to get the solution that lies between π and 2π

    int T = OrbitalPeriod, t = GetDaysElapsed() % T;

    if(t > T / 2)

        bodyAngle = 2.0F * Math.PI - bodyAngle;

    return bodyAngle;

}

Creating a Mandelbrot set bitmap image

(from the Mandelbrot Set Viewer demo)

This routine is used in MainForm to create the main display bitmap (basically a grey-scale representation of the various values returned by MandelbrotSet.IsInSet()).  It computes the complex number represented by each pixel in the bitmap, and converts each complex number's "Mandelbrot value" to a shade of grey, which is then set as the colour of the corresponding pixel.  It also handles the updating of the display and the progress bar and aborts on user cancellation.

private void CreateMandelbrotImage(int imageWidth, int imageHeight,

            int maxIterations, ToolStripProgressBar progressBar)

{

    int x, y, numIterations;

    double a, b;

    int greyScale;

    Color pixelColor;

  

    //Create a new bitmap and fill it with the window's background

    // colour (white) to ensure that it

    // has no transparency even if the user cancels the rendering.

    bmpMandSet = new Bitmap(imageWidth, imageHeight);

    Graphics rbGraphics = Graphics.FromImage(bmpMandSet);

    rbGraphics.Clear(this.BackColor);

    rbGraphics.Dispose();

  

    for (y = 0, b = viewManager.YtoB(0, imageHeight);

            y < imageHeight && isDrawing;

            y++, b -= viewManager.UnitsPerPixelY)

    {

        for (x = 0, a = viewManager.XtoA(0);

            x < imageWidth && isDrawing;

            x++, a+= viewManager.UnitsPerPixelX)

        {

            //Count the number of iterations before the Mandelbrot

            // function becomes unbounded

            numIterations = MandelbrotSet.IsInSet(a, b, maxIterations);

            if (numIterations == maxIterations)

                // we never saw |z| > 2; colour the pixel black

                bmpMandSet.SetPixel(x, y, Color.Black);

            else if (numIterations < maxIterations)

            {

                //Colour the pixel grey, as a percentage of maxIterations

                // (larger number of iterations = darker grey)

                greyScale = (int)(255.0 *

                        ((double)(maxIterations - numIterations)

                            / (double)maxIterations));

                pixelColor = Color.FromArgb(greyScale, greyScale, greyScale);

                bmpMandSet.SetPixel(x, y, pixelColor);

            }

        }

        if ((y % 10 == 0) && isDrawing)

        {

            //We've calculated another 10 rows; show the latest

            // bitmap and update the progress bar.

            this.Refresh();

            progressBar.Value = y;

        }

        //DoEvents() allows the user to cancel the drawing part-way through.

        Application.DoEvents();

    }

}

©2009 Carl Johansen