package polarDust.calculator;
/*
* Copyright (c) 1996 Sorin Lazareanu, All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL purposes and without
* fee is hereby granted provided that this copyright notice
* appears in all copies.
*
*/
/**
*
* This class is an equivalent of a microprocessor in a calculator (minus the
* display logic). It executes commands and is capable of sending messages
* to a display unit (panel).
* Logic organization:
* 2 number registers (double): R1, R2,
* 1 memory register (double): RM.
*
* This class can be further broken down into:
* a Command Control Unit (CCU),
* an Arithmetic and Logic Unit (ALU) and
* Registers
*
*
* The source code.
*
* @version 0.9, 1996.06.04
* @author Sorin Lazareanu
*/
public class Processor01 implements CalcCPU, CalcConstants {
boolean bDigits;
boolean bDecimalPoint;
boolean bUnary;
double dReg1, dReg2, dRegM;
int iOpReg, iDecPlaces = 0;
long lDecimalFactor = 1;
CalcDisplay display;
/**
* Creates a new Processor01 object. Uses a display.
* @see CalcDisplay
*/
public Processor01(CalcDisplay aDisplay) {
display = aDisplay;
c();
}
/**
* Performs the calculations for a digit input.
* @param iDigit 0...9
*/
public void digit(int iDigit) {
double dBufferReg = dReg1;
if (!display.isError()) {
if (!bDigits) {
dReg2 = dReg1;
dBufferReg = 0d;
opRegAssign(iOpReg);
};
if (bDecimalPoint) {
if (lDecimalFactor <= display.maxDigitsFactor()) {
if (dBufferReg >= 0d)
dBufferReg = dBufferReg + iDigit/(double)lDecimalFactor;
else
dBufferReg = dBufferReg - iDigit/(double)lDecimalFactor;
lDecimalFactor *= 10;
iDecPlaces += 1;
};
}
else {
if (dBufferReg >= 0d) dBufferReg = dBufferReg * 10d + iDigit;
else dBufferReg = dBufferReg * 10d - iDigit;
iDecPlaces = 0;
};
reg1ShowWithDecimals(dBufferReg, iDecPlaces);
bDigits = true;
bDecimalPoint = bDecimalPoint;
bUnary = false;
}
}
/**
* Inputs a decimal point.
*/
public void dot() {
if (!display.isError()) {
if (!bDecimalPoint) {
lDecimalFactor = 10;
iDecPlaces = 0;
}
bDigits = bDigits;
bDecimalPoint = true;
bUnary = false;
}
}
/**
* Toggles the sign of the current number (R1 = -R1).
*/
public void sgn() {
if (!display.isError()) {
if (bDecimalPoint && iDecPlaces >= 1) {
reg1ShowWithDecimals(-dReg1, iDecPlaces);
}
else {
reg1Show(-dReg1);
}
}
}
/**
* Clear all registers.
*/
public void c() { mc(); reg1Show(0d); ce(); iOpReg = NUL; }
/**
* Memory register (RM) clear.
*/
public void mc() { regMAssign(0d); }
/**
* Enter or result (=sign ).
*/
public void equ() { result(EQU); }
/**
* Percent operator.
*
For more information see
* the source code method result.
*/
public void prc() { result(PRC); }
/**
* Clear entry (R1 = 0).
*/
public void ce() { unary(CE); }
/**
* Memory read.
*/
public void mr() { unary(MR); }
/**
* Add to memory.
*/
public void madd() { unary(MADD); }
/**
* Substract from memory.
*/
public void msub() { unary(MSUB); }
/**
* Swap registers (R1 with R2).
*/
public void swap() { unary(SWAP); }
/**
* R1 = 1 / R1
*/
public void inv() { unary(INV); }
/**
* R1 = 3.14156...
*/
public void pi() { unary(VPI); }
/**
* R1 = 2.71828...
*/
public void e() { unary(VE); }
/**
* R1 = ln(R1)
*/
public void ln() { unary(LN); }
/**
* R1 = log(R1)
*/
public void log() { unary(LOG); }
/**
* R1 = e^R1
*/
public void exp() { unary(EXP); }
/**
* R1 = square_root(R1)
*/
public void sqrt() { unary(SQRT); }
/**
* R1 = R1 * R1
*/
public void sqr() { unary(SQR); }
/**
* R1 = sin(R1)
*/
public void sin() { unary(SIN); }
/**
* R1 = arcsin(R1)
*/
public void asin() { unary(ASIN); }
/**
* R1 = cos(R1)
*/
public void cos() { unary(COS); }
/**
* R1 = arccos(R1)
*/
public void acos() { unary(ACOS); }
/**
* R1 = tan(R1)
*/
public void tan() { unary(TAN); }
/**
* R1 = arctan(R1)
*/
public void atan() { unary(ATAN); }
/**
* R1 = R1 + R2
*/
public void add() { binary(ADD); }
/**
* R1 = R2 - R1
*/
public void sub() { binary(SUB); }
/**
* R1 = R1 * R2
*/
public void mul() { binary(MUL); }
/**
* R1 = R2 / R1
*/
public void div() { binary(DIV); }
/**
* R1 = R2 ^ R1
*/
public void pow() { binary(POW); }
protected void unary(int iCurrentOp) {
if (!display.isError()) {
switch (iCurrentOp) {
case CE: reg1Show(0d); break;
case MR: reg1Show(dRegM); break;
case VPI: reg1Show(Math.PI); break;
case VE: reg1Show(Math.E); break;
case SWAP:
double dTemp;
dTemp = dReg1;
reg1Show(dReg2);
dReg2 = dTemp;
break;
case SQRT: reg1Show(Math.sqrt(dReg1)); break;
case INV: reg1Show(1d / dReg1); break;
case LN: reg1Show(Math.log(dReg1)); break;
case LOG: reg1Show(Math.log(dReg1) / Math.log(10)); break;
case EXP: reg1Show(Math.exp(dReg1)); break;
case SQR: reg1Show(dReg1 * dReg1); break;
case SIN: reg1Show(Math.sin(toRad(dReg1))); break;
case ASIN: reg1Show(toArc(Math.asin(toRad(dReg1)))); break;
case COS: reg1Show(Math.cos(toRad(dReg1))); break;
case ACOS: reg1Show(toArc(Math.acos(toRad(dReg1)))); break;
case TAN: reg1Show(Math.tan(toRad(dReg1))); break;
case ATAN: reg1Show(toArc(Math.atan(toRad(dReg1)))); break;
case MADD: regMAssign(dRegM + dReg1); break;
case MSUB: regMAssign(dRegM - dReg1);
};
bDigits = false;
bDecimalPoint = false;
bUnary = true;
}
}
protected void binary(int iNextOp){
if (!display.isError()) {
if (bDigits || bUnary) {
reg1Assign(dReg1);
computeBinary();
dReg2 = dReg1;
}
iOpReg = iNextOp;
bDigits = false;
bDecimalPoint = false;
bUnary = false;
}
}
protected void result(int iNextOp){
if (!display.isError()) {
if (!bDigits) opRegAssign(iOpReg);
reg1Assign(dReg1);
opRegAssign(iNextOp);
switch (iNextOp) {
case PRC:
switch (iOpReg) {
case MUL: reg1Show(dReg2 * dReg1 / 100); break;
case DIV: reg1Show(dReg2 / (dReg1 / 100)); break;
case ADD: reg1Show(dReg2 * (1 + dReg1 / 100)); break;
case SUB: reg1Show(dReg2 * (1 - dReg1 / 100));
}
break;
case EQU:
computeBinary();
break;
}
}
if (!display.isError()) reg1Assign(dReg1);
iOpReg = NUL;
bDigits = false;
bDecimalPoint = false;
bUnary = false;
}
private void computeBinary() {
switch (iOpReg) {
case MUL: reg1Show(dReg1 * dReg2); break;
case DIV: reg1Show(dReg2 / dReg1); break;
case ADD: reg1Show(dReg1 + dReg2); break;
case SUB: reg1Show(dReg2 - dReg1); break;
case POW: reg1Show(Math.pow(dReg2, dReg1));
}
}
private double toRad(double dArg) {
return dArg;
}
private double toArc(double dArg) {
return dArg;
}
private protected void regMAssign(double dArg) {
dRegM = display.showM(dArg);
}
private protected void reg1ShowWithDecimals(double dArg, int iDecimals) {
dReg1 = display.showWithDecimals(dArg, iDecimals);
}
private protected void reg1AssignWithDecimals(double dArg, int iDecimals) {
dReg1 = display.assignWithDecimals(dArg, iDecimals);
}
private protected void reg1Show(double dArg) {
dReg1 = display.show(dArg);
}
private protected void reg1Assign(double dArg) {
dReg1 = display.assign(dArg);
}
private protected void opRegAssign(int iOperator) {
Integer oper = new Integer(iOperator);
if (CalcHashtable.containsKey(oper))
display.showOp((String)CalcHashtable.get(oper));
}
}