Examples of mathematics

There are lots of applications of mathematics in this site, ranging from the simple to the not-quite-so-simple.  To give you an idea of what's on offer, I have chosen three examples of varying degrees of complexity.

  1. Preserving aspect ratio
  2. Setting earth and moon inclination
  3. The modpower function 

Preserving aspect ratio

(from the Mandelbrot Set Viewer)

(This is the theory behind the ‘Lock Aspect Ratio’ feature.)  Suppose that the user has selected a display region centred on point (midA, midB), with width displayWidth and height displayHeight. Suppose that the viewing window is bitmapWidth pixels wide and bitmapHeight pixels tall. Then we can compute the number of display units per pixel in each direction thus:

    unitsPerPixelX = displayWidth / bitmapWidth

    unitsPerPixelY = displayHeight / bitmapHeight

If unitsPerPixelX is less than unitsPerPixelY, then to preserve the aspect ratio while still showing all of the selected region we must widen the display region so that unitsPerPixelX = unitsPerPixelY. We do this by setting:

     displayWidth = unitsPerPixelY * bitmapWidth

so the display range on the horizontal axis will be midA ± (unitsPerPixelY * bitmapWidth / 2)

If unitsPerPixelX is greater than unitsPerPixelY then we adjust the height in a similar manner.

Setting earth and moon inclination

(from the Earth Orbit demo)

The Earth Orbit demo renders the earth by wrapping a standard two dimensional Mercator-projection topographical map around a pseudo-spherical three dimensional DirectX object (similarly for the moon).  The demo shows the earth's axis inclined at its real-world value of 23.5° to the ecliptic (and the moon at about 1.5° to its orbital plane).  This is done by supplying appropriate vectors to the DirectX CreateWrap() function.  Here's how:

Suppose that the centre of the earth is located at (x, y, z) = (0, 0, 0)  (all vectors are relative to the earth's reference frame).  Suppose that the reference frame is oriented so that (0, 1, 0) is the "up" direction (this is the way we normally visualise frames).  If we gave our wrap an "up" direction of (0, 1, 0) then the North Pole would be at 90° to the ecliptic - no good.  To get the correct vector, imagine a right angled triangle with a horizontal of length 1 and adjacent angle of 67.5° (i.e. 90° - 23.5°).  You can see that the vertical would have a length of tan(67.5°) (since tan(67.5°) = [length of vertical] / [length of horizontal]).  So when calling CreateWrap() we supply an "up" direction of (x, y, z) = (1, tan(67.5°), 0) (since this is a two-dimensional problem we don't need the z dimension).

 

The modpower function

(from RSA with small numbers)

To cut a long story short, RSA encryption and decryption are done by computing ab mod c, where a is the (encrypted or plaintext) message, c is a special number that is known to all parties (c > a), and b is another special number that is either the public or private key (depending on whether a is encrypted or decrypted).  The trouble is that ab will usually be an incredibly big number that even a computer will not be able to handle in a timely fashion.  Fortunately, there is a trick that enables us to compute ab mod c without needing to compute ab.  In this page we will look at the theory, but you can see the source code for my implementation of a simple 32-bit version here.

The first thing to recognise is that xy mod c = ( x mod c )( y mod c ) mod c.
For example, consider x = 17, y = 8, c = 6:

xy mod c = 136 mod 6 = 4

x mod c = 17 mod 6 = 5

y mod c = 8 mod 6 = 2

( x mod c )( y mod c ) mod c = 5 * 2 mod 6 = 10 mod 6 = 4

Now, let’s break b down into its binary representation.  For example, consider b = 23:

23 = 16 + 4 + 2 + 1 = 24 + 22 + 21 + 20 (ie the binary representation is 101112)

So a23 = a2^4 + 2^2 + 2^1 + 2^0 = a2^4.a2^2. a2^1. a2^0

Thus a23 mod c = a2^4.a2^2. a2^1. a2^0 mod c

= a2^4 mod c . a2^2 mod c . a2^1 mod c . a mod c

This allows us to deal with each ‘bit’ separately.  To handle bit 2, for example, we must compute a2^2 mod c. We can also see that we can ignore the bits that are zero.

Now a2^2 = (a2)2

Once again we can break this down, because ab^d mod c = ((ab mod c) d) mod c, so

(a2)2 mod c = ((a2 mod c)2) mod c

We can handle this as long as we can handle the square of any number < c.

 Now look at a2^3 mod c = ((a2)2) 2 mod c.

This can be rewritten as (((a2 mod c)2) mod c) 2 mod c

This includes the term ((a2 mod c)2) mod c that we already calculated when handling (a2)2, and we can see a pattern emerging:

  • To handle the 0th bit, we compute (a mod c).  Call this residual0
  • To handle the 1st bit, we compute (residual02 mod c).  Call this residual1
  • To handle the 2nd bit, we compute (residual12 mod c).  Call this residual2
  • To handle the nth bit, we compute (residualn-12 mod c).  Call this residualn

 Then ab mod c = residuali . residualj . residualk mod c,

where residuali , residualj , etc are the residuals for the non-zero bits of b.  Computing the residuals is an O(log2 b) operation, and multiplying them together is another O(log2 b) operation.

©2012 Carl Johansen