package com.ppfold.algo;
import java.io.Serializable;
/**
* Extended exponent datatype definition
*
* @author Z.Sukosd
*/
public class PointRes implements Serializable {
private static final long serialVersionUID = 6121110456253627605L;
private static final double LOG_TWO = Math.log(2);
// container for new number representation
private float fraction; // = 0 OR >=1 0R <basis (in absolute value)
private int exponent; // can be any integer, positive and negative
public PointRes(float fraction, int exponent) {
// Input fraction should always have exponent zero!!
this.fraction = fraction;
this.exponent = exponent;
}
public PointRes(PointRes point) {
// Input fraction should always have exponent zero!!
this.fraction = point.fraction;
this.exponent = point.exponent;
}
public void setToFloat(float number) {
this.exponent = 0;
this.fraction = number;
this.convert();
}
public void setToDouble(double number){
long bits = Double.doubleToRawLongBits(number);
double fract = Double
.longBitsToDouble((bits & 0xBfffffffffffffffL) | 0x3ff0000000000000L);
this.fraction = (float) fract;
if (this.fraction == 0f) {
this.fraction = 0;
this.exponent = 0;
} else {
this.exponent = (int) ((bits >> 52) & 0x7FF) - 1023;
}
}
public PointRes(double val) {
long bits = Double.doubleToRawLongBits(val);
double fract = Double
.longBitsToDouble((bits & 0xBfffffffffffffffL) | 0x3ff0000000000000L);
this.fraction = (float) fract;
if (this.fraction == 0f) {
this.fraction = 0;
this.exponent = 0;
} else {
this.exponent = (int) ((bits >> 52) & 0x7FF) - 1023;
}
}
@Override
public PointRes clone() {
PointRes newpoint = new PointRes(this.fraction, this.exponent);
return newpoint.convert();
}
public void copyFrom(PointRes point) {
this.exponent = point.exponent;
this.fraction = point.fraction;
}
public int getExponent() {
return exponent;
}
public void setExponent(int exponent) {
this.exponent = exponent;
}
public float getFraction() {
return fraction;
}
public void setFraction(float val) {
this.fraction = val;
}
public PointRes convert() {
if (fraction == 0f) {
return this;
}
int bits = Float.floatToRawIntBits(fraction);
int mantissaexp = ((bits >> 23) & 0xFF) - 127;
exponent += mantissaexp;
// set exp = 1 and then convert to double:
fraction = Float.intBitsToFloat((bits & 0xBFFFFFFF) | 0x3f800000);
return this;
}
public PointRes takeLogE(){
double fraclog = Math.log(this.fraction);
double exponentlog = LOG_TWO*this.exponent;
this.fraction = (float) (fraclog + exponentlog);
this.exponent = 0;
this.convert();
return this;
}
public PointRes takeLog2(){
double fraclog = Math.log(this.fraction)/LOG_TWO;
this.fraction = (float) (fraclog + this.exponent);
this.exponent = 0;
this.convert();
return this;
}
public PointRes add(double d) {
this.fraction = this.fraction + (float) d;
this.convert();
return this;
}
public PointRes add(PointRes point) {
int diff = this.exponent - point.exponent;
if ((diff < -126 && point.fraction != 0) || this.fraction == 0) {
this.exponent = point.exponent;
this.fraction = point.fraction;
} else if ((diff > 127 && this.fraction != 0) || point.fraction == 0) {
// do nothing, adding zero to the number
} else if (point.exponent != this.exponent) {
float newmantissa = point.fraction
+ setExponent(this.fraction, diff);
this.exponent = point.exponent;
this.fraction = newmantissa;
this.convert();
} else {// equal exponents
this.fraction = this.fraction + point.fraction;
this.convert();
}
return this;
}
public boolean isSignificantlyLessThanZero(){
if(this.fraction < 0f && this.exponent > -8){
return true;
}
else return false;
}
public boolean isLessThan(PointRes point) {
if (this.fraction > 0f && point.fraction > 0f || this.fraction < 0f
&& point.fraction < 0f) {
if (this.exponent > point.exponent) {
return false;
} else if (this.exponent < point.exponent) {
return true;
} else { // case of equal exponents
if (this.fraction < point.fraction) {
return true;
} else {
return false;
}
}
} else if (this.fraction >= 0f && point.fraction <= 0f) {
return false;
} else {
return true;
}
}
public boolean equals(PointRes point) {
if (this.exponent == point.exponent && this.fraction == point.fraction) {
return true;
} else if (this.fraction == 0 && point.fraction == 0) {
return true;
} else {
return false;
}
}
public PointRes multiply(PointRes point) {
this.fraction = this.fraction * point.fraction;
this.exponent = this.exponent + point.exponent;
this.convert();
return this;
}
public PointRes multiply(double prob) {
long bits = Double.doubleToRawLongBits(prob);
// extract fraction part of probability
double fract = Double
.longBitsToDouble((bits & 0xBfffffffffffffffL) | 0x3ff0000000000000L);
// cast to float
float tmpfraction = (float) fract;
if (tmpfraction == 0f) {
// multiplying by zero
this.fraction = 0;
this.exponent = 0;
} else {
// multiplying by a non-zero value
int tmpexponent = (int) ((bits >> 52) & 0x7FF) - 1023;
this.fraction = this.fraction * tmpfraction;
this.exponent = this.exponent + tmpexponent;
this.convert();
}
return this;
}
public PointRes multiply(PointRes point, double prob) {
this.multiply(point);
this.multiply(prob);
return this;
}
public PointRes divide(PointRes point) {
if (point.fraction == 0f) {
System.err.println("Division by zero!");
return null;
}
this.fraction = this.fraction / point.fraction;
this.exponent = this.exponent - point.exponent;
this.convert();
return this;
}
public float toFloat() {
if (fraction == 0f) {
return 0;
} else if (-126 <= exponent && exponent <= 127) {
// normal value
return setExponent(fraction, exponent);
} else if (exponent < -126) {
return 0;
} else {
return fraction > 0f ? Float.POSITIVE_INFINITY
: Float.NEGATIVE_INFINITY;
}
}
public double toDouble() {
if (fraction == 0f) {
return 0;
} else if (-126 <= exponent && exponent <= 127) {
// normal value
return (double) setExponent(fraction, exponent);
} else if (exponent < -126) {
return 0;
} else {
return fraction > 0f ? Double.POSITIVE_INFINITY
: Double.NEGATIVE_INFINITY;
}
}
public String toString() {
return "" + this.fraction + " x 2^" + this.exponent;
}
// exponent must be between -126 and 127
private static float setExponent(float d, int expin) {
int bits = Float.floatToRawIntBits(d);
bits = bits & 0x807fffff; // exp bits are 0
bits = bits | ((expin + 127) << 23);
return Float.intBitsToFloat(bits);
}
public void subtract(PointRes pr, PointRes tmp) {
tmp.copyFrom(pr);
tmp.multiply(-1);
this.add(tmp);
}
}