package mobilebasic;
public class Float {
public static final int ZERO = 0x00000000; // fromString("0.0")
// DEGRAD = (2. * PI) / 360.0 = 0.017453292519943295769236907684886
static final int DEGRAD = 0x0d50d8fe; // Float.MakeFP(1745329, -2, false)
static public int MakeFP(long val, int exp, boolean adjustExp) {
while (Math.abs(val) > 9999999) {
val = val / 10;
if (adjustExp) {
exp += 1;
}
}
/*
* If digits is zero then it is not possible to multiply it
* by 10 any number of times such that the answer will be
* greater than 1000000. It will always be zero!
* The result must also be zero since 0 * x = 0
*/
if (Math.abs(val) > 0) {
while (Math.abs(val) < 1000000) {
val = val * 10;
if (adjustExp) {
exp -= 1;
}
}
} else {
exp = 0;
val = 0;
}
/*
* Create result Float
*/
int result;
if (exp < 0) {
exp = exp + 128;
}
result = ((int) val << 7) | exp;
return result;
}
static public int itof(int ival) {
return MakeFP(ival, 6, true);
}
static public int ftoi(int fp) {
long val = fp >> 7;
int exp = fp & 0x7f;
if (exp > 0x3f) {
exp = exp - 128;
}
//System.out.println("ftoi(" + toString(fp) + ")");
//System.out.println(" exp=" + exp);
//System.out.println(" val=" + val);
// if (exp >= 0)
//{
int shift = 6 - exp;
while (shift > 0) {
val = val / 10;
shift--;
}
while (shift < 0) {
val = val * 10;
shift++;
}
//}
//System.out.println(" val=" + val);
return (int) val;
}
static public String toString(int fp) {
StringBuffer sb = new StringBuffer();
int val = fp >> 7;
int exp = fp & 0x7f;
if (exp > 0x3f) {
exp = exp - 128;
}
//sb.append("sign=" + sign + ", exp=" + exp + ", val=" + val + " ");
if (val < 0) {
sb.append('-');
val = -val;
}
int divisor = 1000000;
if ((exp > 6) || (exp < -6)) {
boolean pointFlag = false;
while (divisor > 0) {
int digit = val / divisor;
val = val - digit * divisor;
sb.append((char) (0x30 + digit));
divisor = divisor / 10;
if (!pointFlag) {
sb.append('.');
pointFlag = true;
}
}
sb.append("E");
if (exp >= 0) {
sb.append('+');
}
sb.append(exp);
} else if (exp >= 0) {
while (divisor > 0) {
int digit = val / divisor;
val = val - digit * divisor;
sb.append((char) (0x30 + digit));
divisor = divisor / 10;
if ((exp == 0) && (divisor > 0)) {
sb.append(".");
}
exp = exp - 1;
if ((exp < -1) && (val == 0)) {
break;
}
}
} else // exp = -1 or less
{
sb.append("0.");
while (divisor > 0) {
exp = exp + 1;
if (exp < 0) {
sb.append('0');
} else {
int digit = val / divisor;
val = val - digit * divisor;
sb.append((char) (0x30 + digit));
divisor = divisor / 10;
}
if (val == 0) {
break;
}
}
}
return sb.toString();
}
static public int fromString(String ascii) {
int sign = 1;
int exp = -1;
int val = 0;
int expVal = 0;
int expSign = 1;
int fp;
final int ERROR = -1;
final int SIGN_OR_DIGIT = 0;
final int DIGIT1 = 1;
final int DIGIT2 = 2;
final int EXPSIGN = 3;
final int GETEXP = 4;
int state = SIGN_OR_DIGIT;
int len = ascii.length();
int offset = 0;
while (offset < len) {
char ch = ascii.charAt(offset);
switch (state) {
case ERROR:
throw new BasicError(8, "Bad Float: " + ascii);
case SIGN_OR_DIGIT:
if (ch == '-') {
offset++;
sign = -1;
state = DIGIT1;
} else if ((ch >= '0') && (ch <= '9')) {
state = DIGIT1;
} else {
state = ERROR;
}
break;
case DIGIT1:
if ((ch >= '0') && (ch <= '9')) {
val = val * 10 + (int) (ch - '0');
if (val != 0) {
exp++;
}
offset++;
} else if (ch == '.') {
state = DIGIT2;
offset++;
} else if ((ch == 'E') || (ch == 'e')) {
state = EXPSIGN;
offset++;
} else {
state = ERROR;
}
break;
case DIGIT2:
if ((ch >= '0') && (ch <= '9')) {
val = val * 10 + (int) (ch - '0');
if (val == 0) {
exp--;
}
offset++;
} else if ((ch == 'E') || (ch == 'e')) {
state = EXPSIGN;
offset++;
} else {
state = ERROR;
}
break;
case EXPSIGN:
if (ch == '+') {
expSign = 1;
offset++;
state = GETEXP;
} else if (ch == '-') {
expSign = -1;
offset++;
state = GETEXP;
} else {
state = ERROR;
}
break;
case GETEXP:
if ((ch >= '0') && (ch <= '9')) {
expVal = expVal * 10 + (int) (ch - '0');
offset++;
} else {
state = ERROR;
}
break;
default:
state = ERROR;
break;
}
}
fp = MakeFP(val * sign, exp + expVal * expSign, false);
return fp;
}
static public int Add(int fp1, int fp2) {
long val1 = fp1 >> 7;
long val2 = fp2 >> 7;
int exp1 = fp1 & 0x7f;
int exp2 = fp2 & 0x7f;
if (exp1 > 0x3f) {
exp1 = exp1 - 128;
}
if (exp2 > 0x3f) {
exp2 = exp2 - 128;
}
/*
* Align values so that they can be added
*/
/*
if (exp1 > exp2)
{
int expDiff = exp1 - exp2; // 1
for (int i=0;i<expDiff;i++)
{
val1 = val1 * 10;
exp1--;
}
}
else if (exp1 < exp2)
{
int expDiff = exp2 - exp1;
for (int i=0;i<expDiff;i++)
{
val2 = val2 * 10;
exp2--;
}
}
*/
while (exp1 > exp2) {
val2 = val2 / 10;
exp2++;
}
while (exp1 < exp2) {
val1 = val1 / 10;
exp1++;
}
val1 = val1 + val2;
return MakeFP(val1, exp1, true);
}
static public int Subtract(int fp1, int fp2) {
//System.out.print(toString(fp1) + "-" + toString(fp2) + "=");
long val1 = fp1 >> 7;
long val2 = fp2 >> 7;
int exp1 = fp1 & 0x7f;
int exp2 = fp2 & 0x7f;
if (exp1 > 0x3f) {
exp1 = exp1 - 128;
}
if (exp2 > 0x3f) {
exp2 = exp2 - 128;
}
/*
* Align values so that they can be subtracted
*/
/*
if (exp1 > exp2)
{
int expDiff = exp1 - exp2; // 1
for (int i=0;i<expDiff;i++)
{
val1 = val1 * 10;
exp1--;
}
}
else if (exp1 < exp2)
{
int expDiff = exp2 - exp1;
for (int i=0;i<expDiff;i++)
{
val2 = val2 * 10;
exp2--;
}
}
*/
while (exp1 > exp2) {
val2 = val2 / 10;
exp2++;
}
while (exp1 < exp2) {
val1 = val1 / 10;
exp1++;
}
val1 = val1 - val2;
return MakeFP(val1, exp1, true);
}
static public int Multiply(int fp1, int fp2) {
long val1 = fp1 >> 7;
long val2 = fp2 >> 7;
int exp1 = fp1 & 0x7f;
int exp2 = fp2 & 0x7f;
if (exp1 > 0x3f) {
exp1 = exp1 - 128;
}
if (exp2 > 0x3f) {
exp2 = exp2 - 128;
}
val1 = (val1 * val2) / 1000000;
exp1 += exp2;
return MakeFP(val1, exp1, true);
}
static public int Divide(int fp1, int fp2) {
long val1 = fp1 >> 7;
long val2 = fp2 >> 7;
int exp1 = fp1 & 0x7f;
int exp2 = fp2 & 0x7f;
if (exp1 > 0x3f) {
exp1 = exp1 - 128;
}
if (exp2 > 0x3f) {
exp2 = exp2 - 128;
}
val1 = (val1 * 1000000) / val2;
exp1 -= exp2;
return MakeFP(val1, exp1, true);
}
/*
*
* fp1 < fp2 = -1
* fp1 = fp2 = 0
* fp1 > fp2 = 1
*/
static public int Compare(int fp1, int fp2) {
int result;
if (fp1 == fp2) {
result = 0;
} else {
int diff = Subtract(fp1, fp2);
//System.out.println(toString(fp1) + " - " + toString(fp2) + " = " + toString(diff));
if (diff < 0) {
result = -1;
} else {
result = 1;
}
}
return result;
}
static public int Negate(int fp) {
long val = fp >> 7;
int exp = fp & 0x7f;
if (exp > 0x3f) {
exp = exp - 128;
}
val = -val;
return MakeFP(val, exp, true);
}
/*
* Log(x+1) = x - (x^2 / 2) + (x^3 / 3) - (x^4 / 4) + ...
*
* where 1 > X >= 0
*/
public static int log(int var0) {
boolean var1 = false;
if (Compare(var0, 0) <= 0) {
throw new BasicError(6, "log(" + toString(var0) + ") : Invalid input");
} else {
int var2;
for (var2 = 0; Compare(var0, 128000000) < 1; var2 = Subtract(var2, 128000000)) {
var0 = Multiply(var0, 347940096);
}
while (Compare(var0, 128000000) >= 1) {
var0 = Divide(var0, 347940096);
var2 = Add(var2, 128000000);
}
int var10000 = var0 = Subtract(var0, 128000000);
int var3 = Negate(Multiply(var10000, var10000));
int var4 = 256000000;
int var7 = var0;
int var5 = var0 + 1;
int var6 = 0;
while (var7 != var5) {
var5 = var7;
var7 = Add(var7, Divide(var3, var4));
var3 = Negate(Multiply(var3, var0));
var4 = Add(var4, 128000000);
if (var6++ > 1000) {
break;
}
}
var7 = Add(var2, var7);
return var7;
}
}
/*
* Exp(x) = 1 + x + (x^2 / 2!) + (x^3 / 3!) + (x^4 / 4!) + ...
* This function doesn't converge for small -ve values of
* < about -6. This seems to be due to integer rounding errors.
*
* This can be solved by remembering that: e^(-x) = 1/(e^x)
*/
public static int exp(int x) {
int result;
if (Compare(x, 0) < 0) {
result = exp2(Negate(x));
result = Divide(128000000, result);
} else {
result = exp2(x);
}
return result;
}
private static int exp2(int var0) {
int var1 = 128000000;
int var2 = var0;
int var3 = 128000000;
int var4 = 128000000;
int var5 = var1 + 1;
int var6 = 0;
while (var1 != var5) {
var5 = var1;
int var7 = Divide(var2, var3);
var1 = Add(var1, var7);
var2 = Multiply(var2, var0);
var4 = Add(var4, 128000000);
var3 = Multiply(var3, var4);
if (var6++ > 1000) {
break;
}
}
if (Compare(var1, 0) < 0) {
var1 = 0;
}
return var1;
}
public static int sqrt(int x) {
int result;
if ((result = Compare(x, 0)) > 0) {
result = exp(Divide(log(x), 256000000));
} else {
if (result != 0) {
throw new BasicError(6, "sqrt(" + toString(x) + ") : Invalid input");
}
result = 0;
}
return result;
}
/*
* Power(x,y) = Exp(Log(x) * y)
*/
public static int pow(int x, int y) {
int result;
if ((result = Compare(x, 0)) > 0) {
result = exp(Multiply(log(x), y));
} else if (result == 0) {
result = 0;
} else {
int var3 = itof(ftoi(y));
if (Compare(Subtract(y, var3), 0) != 0) {
throw new BasicError(6, "pow(" + toString(x) + "," + toString(y) + ") : Invalid input");
}
result = exp(Multiply(log(Negate(x)), y));
if ((var3 & 1) == 1) {
result = Negate(result);
}
}
return result;
}
/*
* Sin(x) = x - (x^3 / 3!) + (x^5 / 5!) - (x^7 / 7!) + ...
*
* Also
* Sin(x) = t/sqrt(1+t^2) where t = tan(x)
*/
public static int sin(int x) {
int var1 = itof(ftoi(Divide(x, 804247680)));
int var2 = Multiply(804247680, var1);
x = Subtract(x, var2);
int result = 0;
int var4 = x;
int var5 = 128000000;
int var6 = 128000000;
int var7 = 1;
int var8 = 0;
while (result != var7) {
var7 = result;
result = Add(result, Divide(var4, var5));
var4 = Negate(Multiply(var4, Multiply(x, x)));
var6 = Add(var6, 128000000);
var5 = Multiply(var5, var6);
var6 = Add(var6, 128000000);
var5 = Multiply(var5, var6);
if (var8++ > 1000) {
break;
}
}
return result;
}
public static int sind(int x) {
return sin(Multiply(x, 223402238));
}
/*
* Cos(x) = 1 - (x^2 / 2!) + (x^4 / 4!) - (x^6 / 6!) + ...
*
* Also
* Cos(x) = 1 / sqrt(1+t^2) where t = tan(x)
* Cos(x) = Sin(X + Pi/2)
*/
public static int cos(int var0) {
return sin(Add(var0, 201061888));
}
static public int cosd(int x)
{
return cos(Multiply(x, DEGRAD));
}
/*
* Tan(x) = Sin(x) / Cos(x)
*/
public static int tan(int x) {
return cos(Multiply(x, 223402238));
}
public static int tand(int x) {
int var1;
if (Compare(var1 = cos(x), 0) != 0) {
int var2 = Divide(sin(x), var1);
return var2;
} else {
throw new BasicError(6, "tan(" + toString(x) + ") : Invalid input");
}
}
public static int sub_5a6(int var0) {
return tand(Multiply(var0, 223402238));
}
public static int asin(int x) {
if (Compare(x, -128000000) >= 0 && Compare(x, 128000000) <= 0) {
int var1 = Multiply(x, x);
if (Compare(var1 = sqrt(Subtract(128000000, var1)), 0) != 0) {
var1 = atan(Divide(x, var1));
} else if (Compare(x, 0) < 0) {
var1 = Negate(201061888);
} else {
var1 = 201061888;
}
return var1;
} else {
throw new BasicError(6, "asin(" + toString(x) + ") : Invalid input");
}
}
public static int asind(int var0) {
return Multiply(asin(var0), 733385985);
}
/*
* ACos(x) = ATan(sqrt(1-x*x)/x)
*
* Also
* ACos(x) = ACot(x/sqrt(1-x*x))
* ACos(x) = Asin(sqrt(1-x*x))
* ACos(x) = 0.5 * PI * asin(-x)
* ACos(x) = 0.5 * PI - asin(x)
*/
public static int acos(int var0) {
return Subtract(Divide(402123904, 256000000), asin(var0));
}
public static int acosd(int var0) {
return Multiply(acos(var0), 733385985);
}
/*
* ATan(x) = x - (x^3 / 3) + (x^5 / 5) - (x^7 / 7) + ...
*/
public static int atan(int x) {
int var1 = Negate(128000000);
int var2 = MakeFP(1570796L, 0, false);
boolean var3 = false;
int var4 = Compare(x, var1);
int var5 = Compare(x, 128000000);
int result;
if (var4 == 0) {
result = Negate(1005309823);
} else if (var5 == 0) {
result = 1005309823;
} else if (var4 < 0) {
result = atan2(Divide(128000000, x));
result = Subtract(Negate(var2), result);
} else if (var5 > 0) {
result = atan2(Divide(128000000, x));
result = Subtract(var2, result);
} else {
result = atan2(x);
}
return result;
}
public static int atand(int x) {
return Multiply(atan(x), 733385985);
}
/*
* atan2 is just a support routine for atan. It is not a atan2(x,y) function!
*/
private static int atan2(int x) {
int result = 0;
int var2 = x;
int var3 = 128000000;
int var4 = 1;
int var5 = 0;
while (result != var4) {
var4 = result;
result = Add(result, Divide(var2, var3));
var2 = Negate(Multiply(var2, Multiply(x, x)));
var3 = Add(var3, 256000000);
if (var5++ > 1000) {
break;
}
}
return result;
}
}