package joshua.discriminative.semiring_parsing;
public class SignedValue {
boolean isPostive;
double logValue;
public SignedValue(){
}
public static SignedValue clone(SignedValue in){
return new SignedValue(in.isPostive, in.logValue);
}
public SignedValue(boolean isPostive_, double logValue_){
this.isPostive = isPostive_;
this.logValue = logValue_;
}
public double convertRealValue(){
return convertRealValue(this);
}
static public double convertRealValue(SignedValue x){
if(x.isPostive)
return Math.exp(x.logValue);
else
return -Math.exp(x.logValue);
}
//realValue: value in real domain
public static SignedValue createSignedValue(double realValue){
if(realValue>=0)
return new SignedValue(true, Math.log(realValue));
else
return new SignedValue(false, Math.log(-realValue));
}
public void setZero(){
isPostive =true;
logValue = Double.NEGATIVE_INFINITY;
}
public void setOne(){
isPostive =true;
logValue = 0;
}
static public SignedValue add(SignedValue x, SignedValue y){
if(x.logValue==Double.NEGATIVE_INFINITY)
return cloneMember(y);
if(y.logValue==Double.NEGATIVE_INFINITY)
return cloneMember(x);
if(x.logValue>=y.logValue)
return atomicSemiringAdd(x, y);
else
return atomicSemiringAdd(y, x);
}
static private SignedValue atomicSemiringAdd(SignedValue large, SignedValue small){
boolean isResPositive = large.isPostive;
double resLogValue;
if( (large.isPostive==true && small.isPostive==true) ||
(large.isPostive==false && small.isPostive==false)){
resLogValue = large.logValue + Math.log(1 + Math.exp(small.logValue-large.logValue));
}else{
resLogValue = large.logValue + Math.log(1 - Math.exp(small.logValue-large.logValue));
}
return new SignedValue(isResPositive, resLogValue);
}
static private SignedValue cloneMember(SignedValue x){
return new SignedValue(x.isPostive, x.logValue);
}
static public SignedValue multi(double x, SignedValue y){
//@todo assume the sign of e^x is always positive
return new SignedValue(y.isPostive, x+y.logValue);
}
static public SignedValue multi(SignedValue x, SignedValue y){
if( (x.isPostive==true && y.isPostive==true) ||
(x.isPostive==false && y.isPostive==false))
return new SignedValue(true, x.logValue+y.logValue);
else
return new SignedValue(false, x.logValue+y.logValue);
}
}