// import becker.robots.*;
// import java.util.Random;

/** A class of code for testing arithmetic
 *
 * @author Duncan Buell
 *
 * These are simple rules to demonstrate arithmetic and precision of
 * arithmetic values.
 *
 * written: 14 October 2007
 *
**/
public class TestCode
{

/* **************************************************************************** */
/** Put in a constructor just in case I want one later.
**/
  public TestCode()
  {
  }
   
/* **************************************************************************** */
/** test the integer arithmetic size
 *
 * Integers on the machines I happen to be using seem to be 32 bits and seem
 * to use twos-complement notation.  This just sets up a loop multiplying an 
 * integer by 2 repetitively.  No error is generated when the multiplication
 * suddenly produces a garbage result. 
 *
 * The integer 2 is bit pattern  00000000 00000000 00000000 00000010 
 * (spaces inserted for readability)
 * Multiplying by 2 is the same as a shift left to produce
 *                  bit pattern  00000000 00000000 00000000 00000100 
 * by 2 again to produce pattern 00000000 00000000 00000000 00001000 
 * and so forth.  When the pattern goes from
 *                               01000000 00000000 00000000 00000000 
 *                            to 10000000 00000000 00000000 00000000 
 * then the number represented goes from 2^30 to -2^31, and then
 * when one multiplies yet again by 2 the pattern becomes all zeros.
 *
 * With negative numbers the story is ever so slightly different. 
 * Minus 2 is represented by     11111111 11111111 11111111 11111110 
 * so multiplication by 2 continues to be a shift left of the bit
 * pattern, but in this case the number that is represented is in
 * fact the correct number up until the pattern becomes all zeros.  
 *
**/
  public void doIntegerTest()
  {
    int theNumberBefore,theNumberAfter;

    System.out.println("");
    System.out.println("Test of positive integer arithmetic sizes");
    theNumberBefore = 1;
    theNumberAfter = 1;
    for(int i = 1; i <= 32; ++i)
    {
      theNumberAfter = theNumberBefore * 2;
      System.out.println("i=" + i + " Before=" + theNumberBefore + ", After=" + theNumberAfter + " is 2^" + i);
      theNumberBefore = theNumberAfter;
    } // for(int i = 1; i <= 32; ++i)

    System.out.println("");
    System.out.println("Test of negative integer arithmetic sizes");
    theNumberBefore = -1;
    theNumberAfter = -1;
    for(int i = 1; i <= 32; ++i)
    {
      theNumberAfter = theNumberBefore * 2;
      System.out.println("i=" + i + " Before=" + theNumberBefore + ", After=" + theNumberAfter + " is -2^" + i);
      theNumberBefore = theNumberAfter;
    } // for(int i = 1; i <= 32; ++i)

  } // public void doIntegerTest();
  
/* **************************************************************************** */
/** test the double precision point arithmetic size
  * All this shows is that doubles are not like integers.  We don't get the
  * erroneous change from positive to negative to zero.  What we would get, if
  * we continued to multiply up, is that we get the most significant digits of
  * the product, not the least significant digits.
**/
  public void doDoubleTest1()
  {
    double theNumberBefore,theNumberAfter;

    System.out.println("");
    System.out.println("Test 1 of positive double precision arithmetic sizes");
    theNumberBefore = 1.0;
    theNumberAfter = 1.0;
    for(int i = 1; i <= 32; ++i)
    {
      theNumberAfter = theNumberBefore * 2.0;
      System.out.println("i=" + i + " Before=" + theNumberBefore + ", After=" + theNumberAfter + " is 2.0^" + i);
      theNumberBefore = theNumberAfter;
    } // for(int i = 1; i <= 32; ++i)

    System.out.println("");
    System.out.println("Test 1 of negative double precision arithmetic sizes");
    theNumberBefore = -1.0;
    theNumberAfter = -1.0;
    for(int i = 1; i <= 32; ++i)
    {
      theNumberAfter = theNumberBefore * 2.0;
      System.out.println("i=" + i + " Before=" + theNumberBefore + ", After=" + theNumberAfter + " is -2.0^" + i);
      theNumberBefore = theNumberAfter;
    } // for(int i = 1; i <= 32; ++i)

  } // public void doDoubleTest1();
  
/* **************************************************************************** */
/** Test the double precision point arithmetic size
  * This test demonstrates double precision sizes
  * If we just square a number repeatedly, it eventually gets too large to be
  * represented.  In Java, on these machines, the result is that "Infinity" is
  * the answer. 
**/
  public void doDoubleTest2()
  {
    double theNumberBefore,theNumberAfter;

    System.out.println("");
    System.out.println("Test 2 of double precision arithmetic sizes");
    theNumberBefore = 2.0;
    theNumberAfter = 2.0;
    for(int i = 1; i <= 12; ++i)
    {
      theNumberAfter = theNumberBefore * theNumberBefore;
      System.out.println("i=" + i + " Before=" + theNumberBefore + ", After=" + theNumberAfter + " is Before^2");
      theNumberBefore = theNumberAfter;
    } // for(int i = 1; i <= 12; ++i)

  } // public void doDoubleTest2();
  
/* **************************************************************************** */
/** Test the double precision point arithmetic size
  * This test demonstrates double precision sizes
  * In IEEE 754 arithmetic, you get 52 bits with which to represent the
  * significand of a double precision value.  
  * What this program does is require the representation of a number that needs
  * more and more precision.
  * The decimal number 1.5    is binary 1.1,    or 0.11 * 2^{-1}
  * The decimal number 1.25   is binary 1.01,   or 0.101 * 2^{-1}
  * The decimal number 1.125  is binary 1.001,  or 0.1001 * 2^{-1}
  * The decimal number 1.0625 is binary 1.0001, or 0.10001 * 2^{-1}
  * If we keep going, eventually we require a number with a 1 at the left edge
  * and a 1 at the right edge with the right edge too many bits to the right.
  * Since we are keeping the MOST significant part of the number, we throw away
  * the tiny part at the right edge, which causes the number to be rounded down
  * to 1.0. 
**/
  public void doDoubleTest3()
  {
    double theAddin, theBaseNumber,theSum;

    System.out.println("");
    System.out.println("Test 3 of double precision arithmetic sizes");
    theBaseNumber= 1.0;
    theAddin = 1.0;
    for(int i = 1; i <= 53; ++i)
    {
      theAddin = theAddin / 2.0;
      theSum = theBaseNumber + theAddin;
      System.out.println("i=" + i + " Base=" + theBaseNumber + " plus Addin=" + theAddin + " equals " + theSum);
    } // for(int i = 1; i <= 53; ++i)

  } // public void doDoubleTest3();
  
} // public class TestCode

