import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;

public class BinaryMath extends JFrame implements ActionListener { 

  // ***** declaration of JFrame variables *****

  
  // define a mainPanel for components
  JPanel mainPanel;  

  // ***** declaration of menu variables *****

  // define a menu bar variable to hold JMenus
  JMenuBar  menuBar;
  
  // define some JMenus and their JMenuItems
  // define a JMenu called fileMenu and add menuItems
  JMenu     fileMenu;
  JMenuItem exitMenuItem;
    
  JMenu     helpMenu;
  JMenuItem helpAndMenuItem;
  JMenuItem helpORMenuItem;
  JMenuItem helpXORMenuItem;
  JMenuItem helpComplementMenuItem;
 
  // define JPanels for a BorderLayout
  JPanel     northPanel;
  JPanel     southPanel;
  JPanel     westPanel;
  JPanel     eastPanel;
  JPanel     centerPanel;
  JPanel     centerTop;
  JPanel     centerTopValue;  
  JPanel     centerMiddle;
  JPanel     centerMiddleValue;
  JPanel     centerBottom;
  JPanel     centerBottomValue;

  ArrayList<JButton> buttons1;
  ArrayList<JButton> buttons1Value;
  ArrayList<JButton> buttons2;
  ArrayList<JButton> resultButtons;
  
  JButton    addButton;
  JButton    subtractButton;

  JButton    orButton;
  JButton    xorButton;
  JButton    andButton;
  JButton    baseButton;
  
  int        currentBase = 2;
  int        theBits = 16;
  
  // change the first two to functionButton1 and 2
  JButton    functionButton1;
  JButton    functionButton2;
  JButton    resultButton3;
  
  
  BaseNumber firstNumberFromScreen;
  BaseNumber secondNumberFromScreen;
  BaseNumber resultNumberFromScreen;
  
  
  JLabel spacer1;
  JLabel spacer2;
  JLabel spacer3;
  JLabel spacer4;
  JLabel spacer5;
  
  JLabel baseTenValue1;
  JLabel baseTenValue2;
  JLabel baseTenValue3;
  
  JLabel baseValueExplanation;
  
  // ***** public void initialize *****

  public int getButtonWidth(int bits)
  {
		int leftSpace = 10;
		int rightSpace = 10;
		int width = 800;
		int gap = 2;
		// int bits = 32;
		int totalButtons = bits + 1; // function button
		int buttonWidth = (int) ( (width - ((totalButtons-1)* gap) - leftSpace - rightSpace) / totalButtons  );
  	    return buttonWidth;
  }
  
  public int getButtonHeight()
  {
  	return 40;
  }
  
  public int getNumberOfButtons()
  {
  	return 16;
  }
  
  
  public void initialize( ) { 


    
    // create a mainPanel for components
    mainPanel = new JPanel();    

    // ***** assignments for menu variables *****

    menuBar            = new JMenuBar();
    
    fileMenu           = new JMenu("File");
    exitMenuItem       = new JMenuItem("Exit");
    
    helpMenu           = new JMenu("Help");
    helpAndMenuItem    = new JMenuItem("& And");
    helpORMenuItem     = new JMenuItem("| OR");
    helpXORMenuItem    = new JMenuItem("^ XOR");
	helpComplementMenuItem = new JMenuItem("~ (1's Complement)");
    
    // add mnemonics to the menu system
    fileMenu.setMnemonic('F');
    exitMenuItem.setMnemonic('x');
    
    // add the menuItem addActionListener(this) calls
    // fileMenu
    exitMenuItem.addActionListener(this);
    helpAndMenuItem.addActionListener(this);
    helpORMenuItem.addActionListener(this);
    helpXORMenuItem.addActionListener(this);
    helpComplementMenuItem.addActionListener(this);
    
    // add menuItems to the fileMenu
    fileMenu.add(exitMenuItem);
    helpMenu.add(helpAndMenuItem);
    helpMenu.add(helpORMenuItem);
    helpMenu.add(helpXORMenuItem);
    helpMenu.add(helpComplementMenuItem);
    
    // add menus to the menuBar
    menuBar.add(fileMenu);
    menuBar.add(helpMenu);
    
    // attach the JMenuBar to the Window
    setJMenuBar(menuBar);
    
    
    // ***** create JPanels for a BorderLayout *****
    northPanel          = new JPanel();
    southPanel          = new JPanel();
    westPanel           = new JPanel();
    eastPanel           = new JPanel();
    centerPanel         = new JPanel();
    centerTop           = new JPanel();
    centerTopValue      = new JPanel();
    centerMiddle        = new JPanel();
    centerMiddleValue   = new JPanel();
    centerBottom        = new JPanel();
    centerBottomValue   = new JPanel();
 

	centerPanel.setLayout(new GridLayout(10,1));
	// centerTop.setLayout(new GridLayout(1,33));
	
	spacer1 = new JLabel("          ");
	spacer2 = new JLabel("          ");
	spacer3 = new JLabel("          ");
	spacer4 = new JLabel("          ");
	spacer5 = new JLabel("          ");
	
	baseValueExplanation = new JLabel("Base 2 value positions are powers of 2  ... 64 32 16 8 4 2 1   (... 2^6  2^5  2^4  2^3  2^2  2^1  2^0)  The first bit is a sign bit.",SwingConstants.CENTER);
	baseValueExplanation.setVerticalAlignment(SwingConstants.TOP);
	updateTitle();
	
	buttons1 = new ArrayList<JButton>();
	buttons1Value = new ArrayList<JButton>();
    buttons2 = new ArrayList<JButton>();
    resultButtons = new ArrayList<JButton>();

	int power = getNumberOfButtons()-1;
		
	Font font = new Font("Courier New",Font.BOLD,12);

	functionButton1 = new JButton("f");
	functionButton1.setFont(font);
	functionButton1.addActionListener(this);
	centerTop.add(functionButton1);
	
		
	functionButton2 = new JButton("f");
	functionButton2.setFont(font);
	functionButton2.addActionListener(this);
	centerMiddle.add(functionButton2);
		
	resultButton3 = new JButton("R");
	resultButton3.setFont(font);
	centerBottom.add(resultButton3);
	
	for (int i=1; i<=getNumberOfButtons(); i++)
	{
		buttons1.add(new JButton("0"));
		buttons1.get(i-1).setFont(font);
		buttons1.get(i-1).addActionListener(this);
		centerTop.add(buttons1.get(i-1));
		
		long value = (long) Math.pow(2,power);
		power--;
		String valueAsString = ""+value;
		if (valueAsString.length() < 2)
		{
			buttons1Value.add(new JButton(""+value));
			buttons1Value.get(i-1).setFont(font);
		}
		else
		{
			buttons1Value.add(new JButton("0"));
			buttons1Value.get(i-1).setFont(font);
		}	
		centerTopValue.add(buttons1Value.get(i-1));
		
		buttons2.add(new JButton("0"));
		buttons2.get(i-1).setFont(font);
		buttons2.get(i-1).addActionListener(this);
		centerMiddle.add(buttons2.get(i-1));
		
		resultButtons.add(new JButton("0"));
		resultButtons.get(i-1).setFont(font);
		centerBottom.add(resultButtons.get(i-1));		
	}
	
	firstNumberFromScreen = new BaseNumber("0",2,16);
	secondNumberFromScreen = new BaseNumber("0",2,16);
	resultNumberFromScreen = new BaseNumber("0",2,16);
	
	
	baseTenValue1 = new JLabel("Base Ten value is 0",SwingConstants.CENTER);
	baseTenValue1.setVerticalAlignment(SwingConstants.TOP);
	baseTenValue2 = new JLabel("Base Ten value is 0",SwingConstants.CENTER);
	baseTenValue2.setVerticalAlignment(SwingConstants.TOP);
	baseTenValue3 = new JLabel("Base Ten value is 0",SwingConstants.CENTER);
	baseTenValue3.setVerticalAlignment(SwingConstants.TOP);
	
	centerPanel.add(spacer1);
	centerPanel.add(baseValueExplanation);
	centerPanel.add(centerTop);
	centerPanel.add(baseTenValue1);

	centerPanel.add(centerMiddle);
	centerPanel.add(baseTenValue2);
	centerPanel.add(centerBottom);
	centerPanel.add(baseTenValue3);
	centerPanel.add(spacer3);
	centerPanel.add(spacer4);
	
	// create the buttons for the southPanel
	addButton = new JButton("Add");
	addButton.addActionListener(this);
	subtractButton = new JButton("Subtract");
	subtractButton.addActionListener(this);

	andButton = new JButton("& (AND)");
	andButton.addActionListener(this);
	orButton = new JButton("| (OR)");
	orButton.addActionListener(this);
	xorButton = new JButton("^ (XOR)");
	xorButton.addActionListener(this);
	baseButton = new JButton("Base 2");
	baseButton.addActionListener(this);
	
	// add the buttons to the southPanel
	southPanel.add(addButton);
	southPanel.add(subtractButton);
	southPanel.add(andButton);
	southPanel.add(orButton);
	southPanel.add(xorButton);
	southPanel.add(baseButton);
	
	
    mainPanel.setLayout(new BorderLayout());
	
    northPanel.setBackground(new Color(115,205,255));
    southPanel.setBackground(new Color(115,205,255));
    westPanel.setBackground(new Color(115,205,255));
    eastPanel.setBackground(new Color(115,205,255));
    // ***** You need to add buttons, etc. to the 5 panels *****


    // ***** add the panels to the mainPanel 5 areas *****
    mainPanel.add(northPanel,BorderLayout.NORTH);
    mainPanel.add(southPanel,BorderLayout.SOUTH);
    mainPanel.add(eastPanel,BorderLayout.EAST);
    mainPanel.add(westPanel,BorderLayout.WEST);
    mainPanel.add(centerPanel,BorderLayout.CENTER);

    // make the mainPanel be the main content area and show it
    setContentPane(mainPanel);
    setVisible(true);  // always show the screen last
  }   // end of public void initialize 

  // ***** default constructor *****

  public BinaryMath( ) { 
    // initialize variables

    setSize(820,600);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setTitle("Base Arithmetic");


    initialize( );

  }

  public void updateTitle()
  {
  	String titleText = "Base "+currentBase+" value positions are powers of "+currentBase+"  ... ";
  	
  	titleText += BaseNumber.baseWithPlaceValueInfo(currentBase,7)+"   ";
  	
  	baseValueExplanation.setText(titleText);
  	
	// baseValueExplanation.setText("(... 2^6  2^5  2^4  2^3  2^2  2^1  2^0)  The first bit is a sign bit.",SwingConstants.CENTER);
  	
  }
  
  public void updateBaseTenValue1()
  {
		String number1 = "";
		for (int k=0; k<buttons1.size(); k++)
		{
			number1 += buttons1.get(k).getText();
		}
		BaseNumber result = new BaseNumber(number1,currentBase,16,false);
		String baseTenValue = ""+result.getNumberInBase10();
		String result16 = "(0x"+result.getNumberInBase(16)+")";
		String result8  = "(0"+result.getNumberInBase(8)+")";
		String placeValueInfo = "";
		if (result.isPositive())
		{
			placeValueInfo = "   " + result.numberWithPlaceValueInfo();
		} 
		String theSign = "";
		if (functionButton1.getText().equals("-"))
			theSign = "-";
    	baseTenValue1.setText("Base ten value is "+theSign+baseTenValue+placeValueInfo+"  "+result16+"  "+result8);
  }

  public void updateBaseTenValue2()
  {
		String number2 = "";
		for (int k=0; k<buttons2.size(); k++)
		{
			number2 += buttons2.get(k).getText();
		}
		BaseNumber result = new BaseNumber(number2,currentBase,16,false);
		String baseTenValue = ""+result.getNumberInBase10();
		String result16 = "(0x"+result.getNumberInBase(16)+")";
		String result8  = "(0"+result.getNumberInBase(8)+")";
		String placeValueInfo = "";
		if (result.isPositive())
		{
			placeValueInfo = "   " + result.numberWithPlaceValueInfo();
		} 
		String theSign = "";
		if (functionButton2.getText().equals("-"))
			theSign = "-";
    	baseTenValue2.setText("Base ten value is "+theSign+baseTenValue+placeValueInfo+"  "+result16+"  "+result8);
  }

  public void updateBaseTenValue3()
  {
		String number3 = "";
		for (int k=0; k<resultButtons.size(); k++)
		{
			number3 += resultButtons.get(k).getText();
		}
		BaseNumber result = new BaseNumber(number3,currentBase,16,false);
		String baseTenValue = ""+result.getNumberInBase10();
		String result16 = "(0x"+result.getNumberInBase(16)+")";
		String result8  = "(0"+result.getNumberInBase(8)+")";
		String placeValueInfo = "";
		if (result.isPositive())
		{
			placeValueInfo = "   " + result.numberWithPlaceValueInfo();
		} 
		
		String theSign = "";
		if (resultButton3.getText().equals("-"))
			theSign = "-";
    	baseTenValue3.setText("Base ten value is "+theSign+baseTenValue+placeValueInfo+"  "+result16+"  "+result8);
    	
  }


  public void updateFirstNumberFromScreen()
  {
  		String theSign = "+";
		String number1 = "";
		for (int k=0; k<buttons1.size(); k++)
		{
			number1 += buttons1.get(k).getText();
		}
		BaseNumber firstNumberFromScreen = new BaseNumber(number1,currentBase,16,false);
		
		if (!firstNumberFromScreen.isPositive())
		{
			theSign = "-";
		} 
  	
  		if (currentBase != 2)
  		{
  			if (functionButton1.getText().equals("+"))
  				theSign = "+";
  			else
  				theSign = "-"; 
  			firstNumberFromScreen = new BaseNumber(number1,currentBase,theBits);
  		}
  	
  }

 // ***** ActionListener interface methods *****

  // start of actionPerformed (ActionListener interface)
  public void actionPerformed(ActionEvent e) {
    Object source = e.getSource();
    if (source == exitMenuItem) {
      System.exit(0);
    }  // end of if

    else if (source == helpAndMenuItem)
    {
    	String helpString = "&  And \n" +
    		                "  1  &  1  = 1  true  & true  = true\n" +
    		                "  1  &  0  = 0  true  & false = false\n" +
    		                "  0  &  1  = 0  false & true  = false\n" +
    		                "  0  &  0  = 0  false & false = false\n" +
    		                
    		                ""	;
    	
    	JOptionPane.showMessageDialog(this,helpString);

    }
    
    else if (source == helpORMenuItem)
    {
    	String helpString = "|  OR \n" +
    		                "  1  |  1  = 1  true  | true  = true\n" +
    		                "  1  |  0  = 1  true  | false = true\n" +
    		                "  0  |  1  = 1  false | true  = true\n" +
    		                "  0  |  0  = 0  false | false = false\n" +
    		                
    		                ""	;
    	
    	JOptionPane.showMessageDialog(this,helpString);

    }

    else if (source == helpXORMenuItem)
    {
    	String helpString = "^  XOR \n" +
    		                "  1  |  1  = 0  true  | true  = false\n" +
    		                "  1  |  0  = 1  true  | false = true\n" +
    		                "  0  |  1  = 1  false | true  = true\n" +
    		                "  0  |  0  = 0  false | false = false\n" +
    		                
    		                ""	;
		//Font font = new Font("Courier New",Font.BOLD,12);
    	//JOptionPane.setFont(font);
    	JOptionPane.showMessageDialog(this,helpString);

    }

    else if (source == helpComplementMenuItem)
    {
    	String helpString = "One's Complement (invert (flip) all bits) \n" +
     		                
    		                ""	;
    	
    	JOptionPane.showMessageDialog(this,helpString);

    }

   else if (source == baseButton)
    {
    	int oldBase = currentBase;
    	
    	currentBase++;
    	if (currentBase > 16)
    	{
    		currentBase = 2;
    	}
    	
    	// now change all
		baseButton.setText("Base "+currentBase);
		
		if (currentBase == 2)
		{
			functionButton1.setText("f");
			functionButton2.setText("f");
	   		andButton.setEnabled(true);
    		orButton.setEnabled(true);
    		xorButton.setEnabled(true);
		}
		else
		{
			functionButton1.setText("+");
			functionButton2.setText("+");
			andButton.setEnabled(true);
    		orButton.setEnabled(true);
    		xorButton.setEnabled(true);
			
		}
		updateTitle();
		updateBaseTenValue1();
		updateBaseTenValue2();
		updateBaseTenValue3();
		
		updateFirstNumberFromScreen();
    }


    else if (source == functionButton1)
    {
    	if (functionButton1.getText().equals("+")  || functionButton1.getText().equals("-") )
    	{
    		// change sign to plus or minus
			if (functionButton1.getText().equals("+"))
			{
				functionButton1.setText("-");	
			}   
			else 		
			{
				functionButton1.setText("+");
			}
    		updateBaseTenValue1(); 
    		   		
    		return;
    	}
    		
    		
    	String choice = JOptionPane.showInputDialog(this,"Enter  >>   >>>   <<   ~   ~+1","",0);

    	if (choice == null)
    	{
    		return;
    	}

    	choice = choice.trim();

    	
    	if (choice.equals("~"))
    	{
    		
			String number1 = "";
			for (int i=0; i<buttons1.size(); i++)
			{
				number1 += buttons1.get(i).getText();
			}
    		BaseNumber num1 = new BaseNumber(number1,2,16);
			BaseNumber result = num1.onesComplement();
		
			String resultNumber = result.numberToString();
			for (int i=0; i<buttons1.size(); i++)
			{
				buttons1.get(i).setText(""+resultNumber.charAt(i));
			}
				
			String baseTenValue = ""+result.getNumberInBase10();
    		baseTenValue1.setText("Base Ten value is "+baseTenValue);
    	}
    	else if (choice.equals("~+1"))
    	{
    		
			String number1 = "";
			for (int i=0; i<buttons1.size(); i++)
			{
				number1 += buttons1.get(i).getText();
			}
    		BaseNumber num1 = new BaseNumber(number1,2,16);
			BaseNumber result = num1.twosComplement();
		
			String resultNumber = result.numberToString();
			for (int i=0; i<buttons1.size(); i++)
			{
				buttons1.get(i).setText(""+resultNumber.charAt(i));
			}
				
			String baseTenValue = ""+result.getNumberInBase10();
    		baseTenValue1.setText("Base Ten value is "+baseTenValue);
    	}

    	else if (choice.substring(0,3).equals(">>>"))
    	{
    		// see if there is a digit after the >>
    		int places = 1;
    		if (choice.length() > 3 && !choice.substring(3).trim().equals(""))
    		{
    			try
    			{
    				places = Integer.parseInt(choice.substring(3).trim());
    			}	
    			catch (Exception e1)
    			{
    				places = 1;
    			}
    		}
    		
			String number1 = "";
			for (int i=0; i<buttons1.size(); i++)
			{
				number1 += buttons1.get(i).getText();
			}
    		BaseNumber num1 = new BaseNumber(number1,2,16);
			BaseNumber result = num1.unsignedBitShiftRight(places);
		
			String resultNumber = result.numberToString();
			for (int i=0; i<buttons1.size(); i++)
			{
				buttons1.get(i).setText(""+resultNumber.charAt(i));
			}
				
			String baseTenValue = ""+result.getNumberInBase10();
    		baseTenValue1.setText("Base Ten value is "+baseTenValue);
    	}

    	else if (choice.substring(0,2).equals(">>"))
    	{
    		// see if there is a digit after the >>
    		int places = 1;
    		if (choice.length() > 2 && !choice.substring(2).trim().equals(""))
    		{
    			try
    			{
    				places = Integer.parseInt(choice.substring(2).trim());
    			}	
    			catch (Exception e1)
    			{
    				places = 1;
    			}
    		}
    		
			String number1 = "";
			for (int i=0; i<buttons1.size(); i++)
			{
				number1 += buttons1.get(i).getText();
			}
    		BaseNumber num1 = new BaseNumber(number1,2,16);
			BaseNumber result = num1.bitShiftRight(places);
		
			String resultNumber = result.numberToString();
			for (int i=0; i<buttons1.size(); i++)
			{
				buttons1.get(i).setText(""+resultNumber.charAt(i));
			}
				
			String baseTenValue = ""+result.getNumberInBase10();
    		baseTenValue1.setText("Base Ten value is "+baseTenValue);
    	}

    	else if (choice.substring(0,2).equals("<<"))
    	{
    		// see if there is a digit after the >>
    		int places = 1;
    		if (choice.length() > 2 && !choice.substring(2).trim().equals(""))
    		{
    			try
    			{
    				places = Integer.parseInt(choice.substring(2).trim());
    			}	
    			catch (Exception e1)
    			{
    				places = 1;
    			}
    		}
    		
			String number1 = "";
			for (int i=0; i<buttons1.size(); i++)
			{
				number1 += buttons1.get(i).getText();
			}
    		BaseNumber num1 = new BaseNumber(number1,2,16);
			BaseNumber result = num1.bitShiftLeft(places);
		
			String resultNumber = result.numberToString();
			for (int i=0; i<buttons1.size(); i++)
			{
				buttons1.get(i).setText(""+resultNumber.charAt(i));
			}
				
			String baseTenValue = ""+result.getNumberInBase10();
    		baseTenValue1.setText("Base Ten value is "+baseTenValue);
    	}


		//JOptionPane.showMessageDialog(this,"Result="+resultNumber+"  Base 10="+baseTenValue);
    }	

    else if (source == functionButton2)
    {

    	if (functionButton2.getText().equals("+")  || functionButton2.getText().equals("-") )
    	{
    		// change sign to plus or minus
			if (functionButton2.getText().equals("+"))
			{
				functionButton2.setText("-");	
			}   
			else 		
			{
				functionButton2.setText("+");
			}
    		updateBaseTenValue2(); 
    		   		
    		return;
    	}
    		
    		
    	String choice = JOptionPane.showInputDialog(this,"Enter  >>   >>>   <<   ~   ~+1","",0);

    	if (choice == null)
    	{
    		return;
    	}

    	choice = choice.trim();

    	
    	if (choice.equals("~"))
    	{
    		
			String number1 = "";
			for (int i=0; i<buttons2.size(); i++)
			{
				number1 += buttons2.get(i).getText();
			}
    		BaseNumber num1 = new BaseNumber(number1,2,16);
			BaseNumber result = num1.onesComplement();
		
			String resultNumber = result.numberToString();
			for (int i=0; i<buttons2.size(); i++)
			{
				buttons2.get(i).setText(""+resultNumber.charAt(i));
			}
				
			String baseTenValue = ""+result.getNumberInBase10();
    		baseTenValue2.setText("Base Ten value is "+baseTenValue);
    	}
    	else if (choice.equals("~+1"))
    	{
    		
			String number1 = "";
			for (int i=0; i<buttons2.size(); i++)
			{
				number1 += buttons2.get(i).getText();
			}
    		BaseNumber num1 = new BaseNumber(number1,2,16);
			BaseNumber result = num1.twosComplement();
		
			String resultNumber = result.numberToString();
			for (int i=0; i<buttons2.size(); i++)
			{
				buttons2.get(i).setText(""+resultNumber.charAt(i));
			}
				
			String baseTenValue = ""+result.getNumberInBase10();
    		baseTenValue2.setText("Base Ten value is "+baseTenValue);
    	}

    	else if (choice.substring(0,3).equals(">>>"))
    	{
    		// see if there is a digit after the >>
    		int places = 1;
    		if (choice.length() > 3 && !choice.substring(3).trim().equals(""))
    		{
    			try
    			{
    				places = Integer.parseInt(choice.substring(3).trim());
    			}	
    			catch (Exception e1)
    			{
    				places = 1;
    			}
    		}
    		
			String number1 = "";
			for (int i=0; i<buttons2.size(); i++)
			{
				number1 += buttons2.get(i).getText();
			}
    		BaseNumber num1 = new BaseNumber(number1,2,16);
			BaseNumber result = num1.unsignedBitShiftRight(places);
		
			String resultNumber = result.numberToString();
			for (int i=0; i<buttons2.size(); i++)
			{
				buttons2.get(i).setText(""+resultNumber.charAt(i));
			}
				
			String baseTenValue = ""+result.getNumberInBase10();
    		baseTenValue2.setText("Base Ten value is "+baseTenValue);
    	}

    	else if (choice.substring(0,2).equals(">>"))
    	{
    		// see if there is a digit after the >>
    		int places = 1;
    		if (choice.length() > 2 && !choice.substring(2).trim().equals(""))
    		{
    			try
    			{
    				places = Integer.parseInt(choice.substring(2).trim());
    			}	
    			catch (Exception e1)
    			{
    				places = 1;
    			}
    		}
    		
			String number1 = "";
			for (int i=0; i<buttons2.size(); i++)
			{
				number1 += buttons2.get(i).getText();
			}
    		BaseNumber num1 = new BaseNumber(number1,2,16);
			BaseNumber result = num1.bitShiftRight(places);
		
			String resultNumber = result.numberToString();
			for (int i=0; i<buttons2.size(); i++)
			{
				buttons2.get(i).setText(""+resultNumber.charAt(i));
			}
				
			String baseTenValue = ""+result.getNumberInBase10();
    		baseTenValue2.setText("Base Ten value is "+baseTenValue);
    	}

    	else if (choice.substring(0,2).equals("<<"))
    	{
    		// see if there is a digit after the >>
    		int places = 1;
    		if (choice.length() > 2 && !choice.substring(2).trim().equals(""))
    		{
    			try
    			{
    				places = Integer.parseInt(choice.substring(2).trim());
    			}	
    			catch (Exception e1)
    			{
    				places = 1;
    			}
    		}
    		
			String number1 = "";
			for (int i=0; i<buttons2.size(); i++)
			{
				number1 += buttons2.get(i).getText();
			}
    		BaseNumber num1 = new BaseNumber(number1,2,16);
			BaseNumber result = num1.bitShiftLeft(places);
		
			String resultNumber = result.numberToString();
			for (int i=0; i<buttons2.size(); i++)
			{
				buttons2.get(i).setText(""+resultNumber.charAt(i));
			}
				
			String baseTenValue = ""+result.getNumberInBase10();
    		baseTenValue2.setText("Base Ten value is "+baseTenValue);
    	}




    }	
    	   
    else if (source == addButton)
    {
    	
    	// numberToString()
    		

		String number1 = "";
		for (int i=0; i<buttons1.size(); i++)
		{
			number1 += buttons1.get(i).getText();
		}
		if (currentBase != 2)
		{
			if (functionButton1.getText().equals("-"))
			{
				number1 = "-" + number1;
			}	
		}

		String number2 = "";
		for (int i=0; i<buttons2.size(); i++)
		{
			number2 += buttons2.get(i).getText();
		}
		if (currentBase != 2)
		{
			if (functionButton2.getText().equals("-"))
			{
				number2 = "-" + number2;
			}	
		}
		
    	BaseNumber num1 = new BaseNumber(number1,currentBase,16);
    	BaseNumber num2 = new BaseNumber(number2,currentBase,16);
		BaseNumber result = num1.add(num2);

		
		String resultNumber = result.numberToString();
		
		if (resultNumber.charAt(0)=='-')
		{
			resultNumber = resultNumber.substring(1);
			resultButton3.setText("-");
		}
		else
		{
			resultButton3.setText("+");	
		}
		
		for (int i=0; i<resultButtons.size(); i++)
		{
			resultButtons.get(i).setText(""+resultNumber.charAt(i));
		}
				
		String baseTenValue = ""+result.getNumberInBase10();
		String placeValueInfo = "";
		if (result.isPositive())
		{
			placeValueInfo = "   " + result.numberWithPlaceValueInfo();
		} 
    	// baseTenValue3.setText("Base Ten value is "+baseTenValue+placeValueInfo);
		updateBaseTenValue3();
    }
 
 
    else if (source == subtractButton)
    {
    	
    	// numberToString()
    		

		String number1 = "";
		for (int i=0; i<buttons1.size(); i++)
		{
			number1 += buttons1.get(i).getText();
		}
		if (currentBase != 2)
		{
			if (functionButton1.getText().equals("-"))
			{
				number1 = "-" + number1;
			}	
		}

		String number2 = "";
		for (int i=0; i<buttons2.size(); i++)
		{
			number2 += buttons2.get(i).getText();
		}
		if (currentBase != 2)
		{
			if (functionButton2.getText().equals("-"))
			{
				number2 = "-" + number2;
			}	
		}

    	BaseNumber num1 = new BaseNumber(number1,currentBase,16);
    	BaseNumber num2 = new BaseNumber(number2,currentBase,16);
		BaseNumber result = num1.subtract(num2);

		
		String resultNumber = result.numberToString();
		if (resultNumber.charAt(0) == '-')
		{
			resultNumber = resultNumber.substring(1);
			resultButton3.setText("-");
		}
		else
		{
			resultButton3.setText("+");	
		}
		
		for (int i=0; i<resultButtons.size(); i++)
		{
			resultButtons.get(i).setText(""+resultNumber.charAt(i));
		}
				
		String baseTenValue = ""+result.getNumberInBase10();
		String placeValueInfo = "";
		if (result.isPositive())
		{
			placeValueInfo = "   " + result.numberWithPlaceValueInfo();
		} 
    	// baseTenValue3.setText("Base Ten value is "+baseTenValue+placeValueInfo);
		updateBaseTenValue3();
    }

    else if (source == orButton)
    {
    	
    	// numberToString()
    		

		String number1 = "";
		for (int i=0; i<buttons1.size(); i++)
		{
			number1 += buttons1.get(i).getText();
		}

		String number2 = "";
		for (int i=0; i<buttons2.size(); i++)
		{
			number2 += buttons2.get(i).getText();
		}

    	BaseNumber num1 = new BaseNumber(number1,2,16);
    	BaseNumber num2 = new BaseNumber(number2,2,16);
		BaseNumber result = num1.bitwiseOr(num2);

		
		String resultNumber = result.numberToString();
		for (int i=0; i<resultButtons.size(); i++)
		{
			resultButtons.get(i).setText(""+resultNumber.charAt(i));
		}
				
		String baseTenValue = ""+result.getNumberInBase10();
		String placeValueInfo = "";
		if (result.isPositive())
		{
			placeValueInfo = "   " + result.numberWithPlaceValueInfo();
		} 
    	//baseTenValue3.setText("Base Ten value is "+baseTenValue+placeValueInfo);
		updateBaseTenValue3();
    }

    else if (source == xorButton)
    {
    	
    	// numberToString()
    		

		String number1 = "";
		for (int i=0; i<buttons1.size(); i++)
		{
			number1 += buttons1.get(i).getText();
		}

		String number2 = "";
		for (int i=0; i<buttons2.size(); i++)
		{
			number2 += buttons2.get(i).getText();
		}

    	BaseNumber num1 = new BaseNumber(number1,2,16);
    	BaseNumber num2 = new BaseNumber(number2,2,16);
		BaseNumber result = num1.bitwiseXOr(num2);

		
		String resultNumber = result.numberToString();
		for (int i=0; i<resultButtons.size(); i++)
		{
			resultButtons.get(i).setText(""+resultNumber.charAt(i));
		}
				
		String baseTenValue = ""+result.getNumberInBase10();
		String placeValueInfo = "";
		if (result.isPositive())
		{
			placeValueInfo = "   " + result.numberWithPlaceValueInfo();
		} 
    	//baseTenValue3.setText("Base Ten value is "+baseTenValue+placeValueInfo);
		updateBaseTenValue3();
    }

    else if (source == andButton)
    {
    	
    	// numberToString()
    		

		String number1 = "";
		for (int i=0; i<buttons1.size(); i++)
		{
			number1 += buttons1.get(i).getText();
		}

		String number2 = "";
		for (int i=0; i<buttons2.size(); i++)
		{
			number2 += buttons2.get(i).getText();
		}

    	BaseNumber num1 = new BaseNumber(number1,2,16);
    	BaseNumber num2 = new BaseNumber(number2,2,16);
		BaseNumber result = num1.bitwiseAnd(num2);

		
		String resultNumber = result.numberToString();
		for (int i=0; i<resultButtons.size(); i++)
		{
			resultButtons.get(i).setText(""+resultNumber.charAt(i));
		}
				
		String baseTenValue = ""+result.getNumberInBase10();
		String placeValueInfo = "";
		if (result.isPositive())
		{
			placeValueInfo = "   " + result.numberWithPlaceValueInfo();
		} 
    	//baseTenValue3.setText("Base Ten value is "+baseTenValue+placeValueInfo);
		updateBaseTenValue3();
    }

   
    else
    {
    	// search for a button	
    	for (int i=0; i<buttons1.size(); i++)
    	{
    		if (source == buttons1.get(i))
    		{
    			String buttonDigit = buttons1.get(i).getText();
    			long value = 0;
    			String newButtonDigit = "0";
    			
    			try
    			{
    			    value = Integer.parseInt(buttonDigit);
    			    value++;
    			    if (value>=currentBase)
    			    {
    			    	value = 0;
    			    }
    			}
    			catch (Exception b1)
    			{
    				
    			}
    			
    			newButtonDigit = "" + value;
    			
    			buttons1.get(i).setText(newButtonDigit);
    			
				String number1 = "";
				for (int k=0; k<buttons1.size(); k++)
				{
					number1 += buttons1.get(k).getText();
				}
				BaseNumber result = new BaseNumber(number1,currentBase,16,false);
				String baseTenValue = ""+result.getNumberInBase10();
				String placeValueInfo = "";
				if (result.isPositive())
				{
					placeValueInfo = "   " + result.numberWithPlaceValueInfo();
				} 
    			//baseTenValue1.setText("Base Ten value is "+baseTenValue+placeValueInfo);
    			updateBaseTenValue1();
    			return;
    		}
    	}
 
    	for (int i=0; i<buttons2.size(); i++)
    	{
    		if (source == buttons2.get(i))
    		{    			
    			String buttonDigit = buttons2.get(i).getText();
    			long value = 0;
    			String newButtonDigit = "0";
    			
    			try
    			{
    			    value = Integer.parseInt(buttonDigit);
    			    value++;
    			    if (value>=currentBase)
    			    {
    			    	value = 0;
    			    }
    			}
    			catch (Exception b2)
    			{
    				
    			}
    			
    			newButtonDigit = "" + value;
    			
    			buttons2.get(i).setText(newButtonDigit);

				String number2 = "";
				for (int k=0; k<buttons2.size(); k++)
				{
					number2 += buttons2.get(k).getText();
				}
				BaseNumber result = new BaseNumber(number2,currentBase,16);
				String baseTenValue = ""+result.getNumberInBase10();
				String placeValueInfo = "";
				if (result.isPositive())
				{
					placeValueInfo = "   " + result.numberWithPlaceValueInfo();
				} 
    			// baseTenValue2.setText("Base Ten value is "+baseTenValue+placeValueInfo);
    			updateBaseTenValue2();
    			return;
    		}
    	}
   	
    }
  }  // end of actionPerformed



  // ***** main method *****
  public static void main(String[] arguments) {
    BinaryMath binaryMath = new BinaryMath( );
  }


} // end of class BinaryMath



// notes:
// 1) the bases must be the same
// 2) subtract ???, multiply ???, divide ???
// 3) we cannot add negative numbers either
// 4) this does not support adding of negative numbers yet except for binary if the bits = 32
// 5) no support for decimals

// add ~ & | ^


class BaseNumber {

	String sign;
	ArrayList <Integer> number;
	int base = 10;
	int bits = 0;
	  
	    
    public BaseNumber(ArrayList <Integer> newNumber) {
    	sign = "+";
    	this.base = 10;
    	this.number = newNumber;
    }


    public BaseNumber(ArrayList <Integer> newNumber, int base) {
    	sign = "+";
    	this.base = base;
    	this.number = newNumber;
    }

    public BaseNumber(ArrayList <Integer> newNumber, int base, int bits) {
    	sign = "+";
    	if (base==2 && bits!=0 && newNumber.get(0)==1)
    		sign = "-";
    	this.base = base;
    	this.number = newNumber;
    	this.bits = bits;
    }
    
    
    public BaseNumber(ArrayList <Integer> newNumber, int base, int bits, String sign) {
    	this.sign = sign;
    	this.base = base;
    	this.number = newNumber;
    	this.bits = bits;
    }

    // base 10 only 
    public BaseNumber(int newNumber) {
    	sign = "+";
    	if (newNumber < 0)
    		sign = "-";
    	newNumber = Math.abs(newNumber);
    	this.base = 10;
    	String s = ""+newNumber;
    	number = new ArrayList<Integer>();
    	for (int i=0; i<s.length(); i++)
    	{
    		number.add(s.charAt(i)-48);
    	}
    }
 
 
 	// converts the base ten newNumber to the given base
    public BaseNumber(long newNumber, int base) {
    	sign = "+";
    	if (newNumber < 0)
    		sign = "-";
    	this.base = base;
    	String s = "";
    	newNumber = Math.abs(newNumber);
    	// fix me this does not work if over base 10
    	while (newNumber > 0)
    	{
    		int rem = (int) (newNumber % base);
    		switch (rem)
    		{
    			case 10 : s = "A" + s; break;
    			case 11 : s = "B" + s; break;
    			case 12 : s = "C" + s; break;
    			case 13 : s = "D" + s; break;
    			case 14 : s = "E" + s; break;
    			case 15 : s = "F" + s; break;
    			
    			default : s = rem + s; break;	
    		}
    		
    		newNumber /= base;	
    	}
    	
    	number = new ArrayList<Integer>();
    	for (int i=0; i<s.length(); i++)
    	{
			if (s.charAt(i)=='A')
				number.add(10);
			else if (s.charAt(i)=='B')
				number.add(11);
			else if (s.charAt(i)=='C')
				number.add(12);
			else if (s.charAt(i)=='D')
				number.add(13);
			else if (s.charAt(i)=='E')
				number.add(14);
			else if (s.charAt(i)=='F')
				number.add(15);
    		else
    			number.add(s.charAt(i)-48);
    	}
    	
    	if (base==2 && sign=="-")
    	{
    		twosComplementOfNumber();	
    	}
    }
   
   
    public BaseNumber(String newNumber) {

    	// sets sign and newNumber ("+" or "-" or no sign)
    	newNumber = getNewNumberSigned(newNumber);
		bits = 0;
    	this.base = 10;
    	String s = newNumber;
    	number = new ArrayList<Integer>();
    	for (int i=0; i<s.length(); i++)
    	{
    		number.add(s.charAt(i)-48);
    	}
    }


    public BaseNumber(String newNumber, int base) {

    	// sets sign and newNumber ("+" or "-" or no sign)
    	newNumber = getNewNumberSigned(newNumber);

    	this.base = base;
    	String s = newNumber;
    	number = new ArrayList<Integer>();
    	for (int i=0; i<s.length(); i++)
    	{
    		number.add(s.charAt(i)-48);
    	}
    	
    	if (base==2 && sign=="-")
    	{
    		twosComplementOfNumber();	
    	}
    }

	// for base 2 only
	// the number may already be negative and is already in twos complement form
    public BaseNumber(String newNumber, int base, int bits, boolean convertToTwosComplement) {
    	
    	this.bits = bits;
    	
    	// sets sign and newNumber ("+" or "-" or no sign)
    	newNumber = getNewNumberSigned(newNumber);
    	
    	if (base==2 && newNumber.charAt(0)=='1' && !convertToTwosComplement)
    		sign = "-";
    		 	
    	this.base = base;
    	String s = newNumber;
    	number = new ArrayList<Integer>();
    	for (int i=0; i<s.length(); i++)
    	{
    		number.add(s.charAt(i)-48);
    	}
    	padWithZeroes(number,bits-number.size());
    	if (base==2 && convertToTwosComplement && sign.equals("-"))
    	{
    		twosComplementOfNumber();
    	}
    }


	// for base 2 only
    public BaseNumber(String newNumber, int base, int bits) {
    	
    	this.bits = bits;
    	
    	// sets sign and newNumber ("+" or "-" or no sign)
    	newNumber = getNewNumberSigned(newNumber);
    		
    	this.base = base;
    	String s = newNumber;
    	number = new ArrayList<Integer>();
    	for (int i=0; i<s.length(); i++)
    	{
    		number.add(s.charAt(i)-48);
    	}
    	padWithZeroes(number,bits-number.size());
    	if (base==2 && sign.equals("-"))
    	{
    		twosComplementOfNumber();
    	}
    }


	// gets the sign set and newNumber set
	public String getNewNumberSigned(String newNumber)
	{
    	if (newNumber.charAt(0)=='+')
    	{
    		sign = "+";
    		newNumber = newNumber.substring(1);
    	}
    	else if (newNumber.charAt(0)=='-')
    	{
    		sign = "-";
    		newNumber = newNumber.substring(1);
    	}
    	else
    		sign = "+";
    	
    	return newNumber;		
	}
	
	
	public ArrayList<Integer> getNumberAsArray()
	{
		return number;	
	}
	
	
	public int size()
	{
		return number.size();
	}
	
	
	public Integer getDigit(int i)
	{
		return number.get(i);
	}
	
	public String getSign()
	{
		return sign;
	}
	
	public boolean isPositive()
	{
		if (sign.equals("+"))
			return true;
		return false;			
	}

	public boolean isNegative()
	{
		if (sign.equals("-"))
			return true;
		return false;			
	}

	public int getBase()
	{
		return base;
	}

	public void setBase(int base)
	{
		this.base = base;
	}
	
	
	// only for binary numbers
	public void onesComplementOfNumber()
	{		
		for (int i=0; i<number.size(); i++)
		{
			if (number.get(i) == 1)
			{
				number.set(i,0);
			}
			else
			{
				number.set(i,1);
			}
		}
	}
	
	
	// only for binary numbers
	public void twosComplementOfNumber()
	{
		BaseNumber newNumber = onesComplement();
		newNumber = newNumber.add(new BaseNumber("1",2));
		number = newNumber.getNumberAsArray();	
	}
	
	
	// only for binary numbers
	public BaseNumber onesComplement()
	{
		ArrayList <Integer> newNumber = new ArrayList<Integer>();
		
		for (int i=0; i<number.size(); i++)
		{
			if (number.get(i) == 1)
			{
				newNumber.add(0);
			}
			else
			{
				newNumber.add(1);
			}
		}
		
		String newSign;
		if (sign.equals("+"))
			newSign = "-";
		else
			newSign = "+";
		return new BaseNumber(newNumber,getBase(),bits,newSign);
	}
	
	
	// only for binary numbers
	public BaseNumber twosComplement()
	{
		BaseNumber newNumber = onesComplement();
		return newNumber.add(new BaseNumber("1",2));	
	}
	

	// only for binary numbers
	public BaseNumber twosComplement(BaseNumber other)
	{
		BaseNumber newNumber = other.onesComplement();
		return newNumber.add(new BaseNumber("1",2));	
	}

	
	// only for binary numbers
	// the sign bit is filled from the left
	// what if numPlaces is not in the range of 0..31?
	// then numPlaces & 0x1f becomes the shift amount
	// the right most bits fall off the edge of the world
	public BaseNumber bitShiftRight(int numPlaces)	
	{
		numPlaces = numPlaces & 0x1f;
		
		ArrayList <Integer> newNumber = new ArrayList<Integer>();
		fill(newNumber,number);
		
		int k = newNumber.size()-1;
		for (int i=1; i<=numPlaces; i++)
		{
			if (newNumber.size()==0)
				break;
			newNumber.remove(k);
			if (bits!=0)	
			{
				if (sign.equals("-"))
				{
					newNumber.add(0,1);	
				}
				else
				{
					newNumber.add(0,0);
				}
			}
			k = newNumber.size()-1;
		}
		BaseNumber aNumber = new BaseNumber(newNumber,2,bits,sign);
		return aNumber;
	}

	// only for binary numbers
	// zeroes are filled from the left
	// what if numPlaces is not in the range of 0..31?
	// then numPlaces & 0x1f becomes the shift amount
	public BaseNumber unsignedBitShiftRight(int numPlaces)	
	{
		numPlaces = numPlaces & 0x1f;
		
		ArrayList <Integer> newNumber = new ArrayList<Integer>();
		fill(newNumber,number);
		
		int k = newNumber.size()-1;
		for (int i=1; i<=numPlaces; i++)
		{
			if (newNumber.size()==0)
				break;
			newNumber.remove(k);
			if (bits!=0)	
			{
				newNumber.add(0,0);
			}
			k = newNumber.size()-1;
		}
		BaseNumber aNumber = new BaseNumber(newNumber,2,bits,sign);
		return aNumber;
	}


	
	// only for binary numbers
	// right most bits are filled with zeroes
	public BaseNumber bitShiftLeft(int numPlaces)	
	{
		numPlaces = numPlaces & 0x1f;

		ArrayList <Integer> newNumber = new ArrayList<Integer>();
		fill(newNumber,number);
		
		int k = newNumber.size()-1;
		for (int i=1; i<=numPlaces; i++)
		{
			if (newNumber.size()==0)
				break;
			newNumber.remove(1); // don't remove the sign bit
			if (bits!=0)	
			{
				if (sign.equals("-"))
				{
					newNumber.add(0);	
				}
				else
				{
					newNumber.add(0);
				}
			}
			k = newNumber.size()-1;
		}
		BaseNumber aNumber = new BaseNumber(newNumber,2,bits,sign);
		return aNumber;
	}

	
    public void padWithZeroes(ArrayList<Integer> aNumber, int numZeroes)
    {
    	for (int i=1; i <= numZeroes; i++)
    	{
    		aNumber.add(0,0); // insert 0 at the beginning
    	}
    }
        
    
    public String padWithSpacesOnLeft(String num, int numSpaces)
    {
    	for (int i=1; i<=numSpaces; i++)
    	{
    		num = " " + num;
    	}
    	return num;
    }
    	
    	
    public void fill(ArrayList<Integer> to, ArrayList<Integer> from)
    {
    	to.clear();
    	for (int i=0; i<from.size(); i++)
    	{
    		to.add(from.get(i));	
    	}
    } 
    
    
    public long getNumberInBase10()
    {
    	long sum = 0;
    	long value = 1;
    	// what if we are in base 2 and bits != 0? OK
    	// 
    	
    	// for base 2, this number might be in two's complement form  works ok for int and bits == 32 but otherwise no
    	
    	
    	
    	
        for (int i=number.size()-1; i>=0; i--)
        {
        	if (bits!=0 && base==2 && i==0)
        		sum += (number.get(i)*-1)*value;
        	else	
        		sum += number.get(i)*value;
        	value *= base;
        }
        
        if (sign.equals("-"))
        {
        	if (base != 2)
        		sum *= -1;
        }
		return sum;
    }
    
    public String getNumberInBase(int inBase)
    {
    	long base10Number = getNumberInBase10();
    	
    	BaseNumber newNumber = new BaseNumber(base10Number, inBase);
    	newNumber.setBase(inBase);
        
        return newNumber.numberToString();    	
    	
	}



    // you must have the same size
    public int isBiggestNoSign(ArrayList<Integer> big, ArrayList<Integer> small)
    {
   		for (int k=0; k<big.size(); k++)
    	{
    		if (big.get(k) > small.get(k))
    			return 1;
    		else if (big.get(k) < small.get(k))
    			return -1;
    			
    	}
    	return 0;
    }
    
    
    // i is the position in the array that needs to borrow in order to substract
    public void borrow(int i, ArrayList<Integer> num)
    {
    	int startValue = num.get(i);
    	
    	do 
    	{
    		for (int k=i-1; k>=0; k--)
    		{
    			if (num.get(k)>0) // we can borrow
    			{
    				num.set(k,num.get(k)-1);
    				num.set(k+1,num.get(k+1)+base); // + base ????????????????????????????
    				break;
    			}
    		
    		}
    	} while (num.get(i) == startValue);    	
    }
    
    
    // the incoming ArrayLists should be in order and the same size
    public ArrayList<Integer> subtractBigMinusSmall(ArrayList<Integer> big, ArrayList<Integer> small)
    {
    	
    	ArrayList <Integer> newNumber = new ArrayList<Integer>();

    	for (int k=big.size()-1; k>=0; k--)
    	{
    		if (big.get(k) >= small.get(k))
    		{
    			int newDigit = big.get(k) - small.get(k);
    			newNumber.add(0,newDigit);
    		}
    		else
    		{
    			borrow(k,big);
    			int newDigit = big.get(k) - small.get(k);
    			newNumber.add(0,newDigit);    				
    		}
    		
    	}
    	
    	return newNumber;
    }
    
    
    // for binary only
    // does the sign and lead bit stay the same no, they are just ored as well
    // so, the only way to get a positive result is to have two positive numbers ored
    public BaseNumber bitwiseOr(BaseNumber other)
    {
    	ArrayList <Integer> otherNumber = other.number;

    	// use separate arrays so that we don't have leading zeroes added
    	
    	ArrayList <Integer> number1 = new ArrayList<Integer>();
    	fill(number1,number);
    	ArrayList <Integer> number2 = new ArrayList<Integer>();
    	fill(number2,otherNumber);


     	// make the numbers the same length (size)   	
    	if (number.size() < otherNumber.size())
    	{
    		padWithZeroes(number1,otherNumber.size()-number.size());
    	}
    	else if (number.size() > otherNumber.size())
    	{
    		padWithZeroes(number2,number.size()-otherNumber.size());	
    	}	


    	ArrayList<Integer> result = new ArrayList<Integer>();

    	for (int i=number1.size()-1; i>=0; i--)
    	{
    		// if (number1.get(i) | number2.get(i) == 1)
    		if (number1.get(i)==1 || number2.get(i)==1)
    			result.add(0,1);
    		else
    			result.add(0,0);
    	}

    	
    	return new BaseNumber(result,base,bits,sign);
	
    }
    

    // for binary only
    // does the sign and lead bit stay the same no, they are just xored as well
    public BaseNumber bitwiseXOr(BaseNumber other)
    {
    	ArrayList <Integer> otherNumber = other.number;

    	// use separate arrays so that we don't have leading zeroes added
    	
    	ArrayList <Integer> number1 = new ArrayList<Integer>();
    	fill(number1,number);
    	ArrayList <Integer> number2 = new ArrayList<Integer>();
    	fill(number2,otherNumber);


     	// make the numbers the same length (size)   	
    	if (number.size() < otherNumber.size())
    	{
    		padWithZeroes(number1,otherNumber.size()-number.size());
    	}
    	else if (number.size() > otherNumber.size())
    	{
    		padWithZeroes(number2,number.size()-otherNumber.size());	
    	}	


    	ArrayList<Integer> result = new ArrayList<Integer>();

    	for (int i=number1.size()-1; i>=0; i--)
    	{
    		if (  (number1.get(i) ^ number2.get(i)) == 1)
    			result.add(0,1);
    		else
    			result.add(0,0);
    	}

    	
    	return new BaseNumber(result,base,bits,sign);
	
    }
    


    // for binary only
    // does the sign and lead bit stay the same no, they are just anded as well
    // so, the only way to get a negative result is to have two negative numbers anded
    public BaseNumber bitwiseAnd(BaseNumber other)
    {
    	ArrayList <Integer> otherNumber = other.number;

    	// use separate arrays so that we don't have leading zeroes added
    	
    	ArrayList <Integer> number1 = new ArrayList<Integer>();
    	fill(number1,number);
    	ArrayList <Integer> number2 = new ArrayList<Integer>();
    	fill(number2,otherNumber);


     	// make the numbers the same length (size)   	
    	if (number.size() < otherNumber.size())
    	{
    		padWithZeroes(number1,otherNumber.size()-number.size());
    	}
    	else if (number.size() > otherNumber.size())
    	{
    		padWithZeroes(number2,number.size()-otherNumber.size());	
    	}	


    	ArrayList<Integer> result = new ArrayList<Integer>();

    	for (int i=number1.size()-1; i>=0; i--)
    	{
    		if (number1.get(i)==1 && number2.get(i)==1)
    			result.add(0,1);
    		else
    			result.add(0,0);
    	}

    	
    	return new BaseNumber(result,base,bits,sign);
	
    }
    

    
    // for binary ???
    public BaseNumber subtract(BaseNumber other)
    {
    	if (base==2 && other.base==2)
    	{
    		// we will need to convert other.base to two's complement form
    		other = twosComplement(other);
    	}

    	else if (other.sign.equals("+"))
    	{
    		other.sign = "-";
    	}
    	else
    	{
    		other.sign = "+";
    	}
		
		return add(other);
    }
    
    
    
    // this does not support adding of negative numbers yet except for binary  fixed!
    
    public BaseNumber add(BaseNumber other)
    {

    	ArrayList <Integer> otherNumber = other.number;

    	// use separate arrays so that we don't have leading zeroes added
    	
    	ArrayList <Integer> number1 = new ArrayList<Integer>();
    	fill(number1,number);
    	ArrayList <Integer> number2 = new ArrayList<Integer>();
    	fill(number2,otherNumber);


     	// make the numbers the same length (size)   	
    	if (number.size() < otherNumber.size())
    	{
    		padWithZeroes(number1,otherNumber.size()-number.size());
    	}
    	else if (number.size() > otherNumber.size())
    	{
    		padWithZeroes(number2,number.size()-otherNumber.size());	
    	}	


    	ArrayList<Integer> result = new ArrayList<Integer>();


    	if (base==2 && other.base==2)
    	{
    		// this add method stores base 2 numbers in twos complement form, so fall below
    	}
    	else if (sign.equals("+") && other.sign.equals("+"))
    	{
    		// fall below
    	}
    	else if (sign.equals("-") && other.sign.equals("-")) 
    	{
    		// fall below	
    	}
    	else if (  (sign.equals("+") && other.sign.equals("-")) || (sign.equals("-") && other.sign.equals("+"))  ) 
    	{
    		// call subtract
    		int x = isBiggestNoSign(number1, number2);
    		String newSign = "+";
    		System.out.println("inside add 1");	
    		if (x>=0)
    		{    			
    			result = subtractBigMinusSmall(number1, number2);
    			newSign = sign;
    			System.out.println("inside add bigger");	

    		}
    		else
    		{
    			result = subtractBigMinusSmall(number2, number1);
    			newSign = other.sign;
    			System.out.println("inside add smaller");
    		}
    		System.out.println("inside add 2");	
    		return new BaseNumber(result,base,bits,newSign);	
    	}
    	
    	
    	
    	int carry = 0;
    	
    	for (int i=number1.size()-1; i>=0; i--)
    	{
    		int sum = number1.get(i) + number2.get(i) + carry;
    		if (sum < base)
    		{
    			carry = 0;
    			result.add(0,sum);
    		}
    		else
    		{
    			result.add(0,sum%base);
    			carry = sum/base;  
    		}
    	}
    	
    	if (carry>0&&bits==0)
    	{
    		result.add(0,carry);
    	}
    	
    	return new BaseNumber(result,base,bits,sign);
    		
    }	
    
    
    public long getValueOfFirstDigit()
    {
    	long value = 1;    	
    	
        for (int i=number.size()-1; i>=0; i--)
        {
        	value *= base;
        }
        
		return value;
    }
	
	
	public long getValueOfDigit(int n) // n-1, n-2, ..., 3, 2, 1
    {
    	long value = 1;    	
    	
        for (int i=number.size()-1; i>n; i--)
        {
        	value *= base;
        }
        
        if (bits!=0 && n==0 && sign.equals("-"))
        	return -1*value;
		return value;
    }


	// this shows the number with the place value below it
    public String getPlaceValue()
    {
    	long x = getValueOfFirstDigit();
    	String line2 = " "+x;
    	int digitLength = line2.length();
		line2  = "";
		
        for (int i=number.size()-1; i>=0; i--)
        {
        	String num = ""+getValueOfDigit(i);
        	num = padWithSpacesOnLeft(num,digitLength-num.length());
        	line2 = num + line2;
        }

		

    	String line1 = "";
        for (int i=0; i<number.size(); i++)
        {
        	String num = ""+number.get(i);
        	num = padWithSpacesOnLeft(num,digitLength-num.length());
        	line1 += num;
        }
    	    	
    	
    	return line1+"\n"+line2;
    }	
    	
    public void stripLeadingZeroes()
    {
        for (int i=0; i<number.size(); i++)
    	{
    		if (number.get(i) == 0)
    		{
    			number.remove(i);
    			i--;	
    		}
    		else
    		{
    			break;
    		}
    	}
    }
    
    public static String baseWithPlaceValueInfo(int theBase, int places)
    {    	    	    	   	
    	String info = ""; 
    	long value = 1;
    	for (int i=0; i<places; i++)
    	{
 	    	info = value + info;
    		value *= theBase;
    		if (i<places-1)
    		{
    			info = " " + info;
    		}
    	}
    	 
    	    	
    	return info;
    }
    
    public String numberWithPlaceValueInfo()
    {
    	if (bits == 0)
    	{
    		stripLeadingZeroes();
    	}
    	    	
    	// find first nonzero digit (ignore the sign bit)
    	int stop = 0;
    	for (int i=1; i<number.size(); i++)
    	{
    		if (number.get(i) > 0)
    		{
    			stop = i;
    			break;
    		}
    		if (i==number.size()-1)
    		{
    			stop = number.size();
    		}
    	}
    	
    	
    	String info = ""; 
    	long value = 1;
    	for (int i=number.size()-1; i>=stop; i--)
    	{
    		if (base > 10 && number.get(i)>=10)
    		{
    			info = ((char)(55+number.get(i))) +"*"+value + info;
    		}
    		else
    		{    		
	    		info = number.get(i)+"*"+value + info;
    		}
    		if (i!=stop)
    		{
    			info = " + " + info;
    		}
    		value *= base;
    	}
    	 
    	    	
    	return info;
    }


    public String numberToString()
    {
    	if (bits == 0)
    	{
    		stripLeadingZeroes();
    	}
    	
    	String output = "";
    	
    	if (base!=2 && sign.equals("-"))
    		output += "-";
    		
    	for (int i=0; i<number.size(); i++)
    	{
    		if (base > 10 && number.get(i)>=10)
    		{
    			output += (char)(55+number.get(i));
    		}
    		else
    		{    		
	    		output += number.get(i);
    		}
    	}
    	    	
    	return output;
    }
  
  
      
    public String toString()
    {
    	if (bits == 0)
    	{
    		stripLeadingZeroes();
    	}
    	
    	String output = "";
    	
    	if (base!=2 && sign.equals("-"))
    		output += "-";
    		
    	for (int i=0; i<number.size(); i++)
    	{
    		if (base > 10 && number.get(i)>=10)
    		{
    			output += (char)(55+number.get(i));
    		}
    		else
    		{    		
	    		output += number.get(i);
    		}
    	}
    	
    	if (base != 10)
    	{
    		long x = getNumberInBase10();
    		output += "  (";
    		
    		output += x + " in base 10)";	
    	}
    	
    	return output;
    }
}


