/*******************************************************************************
* Copyright 2012 University of Southern California
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This code was developed by the Information Integration Group as part
* of the Karma project at the Information Sciences Institute of the
* University of Southern California. For more information, publications,
* and related projects, please see: http://www.isi.edu/integration
******************************************************************************/
package edu.isi.karma.modeling.semantictypes.mycrf.math ;
import edu.isi.karma.modeling.semantictypes.myutils.Prnt;
/**
* This class represents the large numbers (as large as 10^1000) which are generated
* due to exponential computations.
* It supports basic operations such as addition, and multiplication.
*
* @author amangoel
*
*/
public class LargeNumber {
double mantissa ;
int exp ;
public LargeNumber(double d) {
if(d == 0.0) {
mantissa = 0.0 ;
exp = 0 ;
}
else {
exp = (int) Math.log10(d) ;
mantissa = d / Math.pow(10, exp) ;
}
}
public LargeNumber(double mantissa, int exp) {
this.mantissa = mantissa ;
this.exp = exp ;
}
public LargeNumber(LargeNumber ln) {
this.mantissa = ln.mantissa ;
this.exp = ln.exp ;
}
public void setValue(double d) {
if(d == 0.0) {
mantissa = 0.0 ;
exp = 0 ;
}
else {
exp = (int) Math.log10(d) ;
mantissa = d / Math.pow(10, exp) ;
}
}
public void setValue(double mantissa, int exp) {
this.mantissa = mantissa ;
this.exp = exp ;
}
public void setValue(LargeNumber largeNumber) {
mantissa = largeNumber.mantissa ;
exp = largeNumber.exp ;
}
static public LargeNumber add(LargeNumber n1, LargeNumber n2) {
double m ;
int e ;
if(n1.mantissa == 0.0)
return n2 ;
else if(n2.mantissa == 0.0)
return n1 ;
if(Math.abs(n1.exp - n2.exp) > 300 && n1.mantissa != 0.0 && n2.mantissa != 0.0) {
//Prn.prn("The difference between the exponentials is more than 300. n1 = " + n1 + " and n2 = " + n2) ;
if(n1.exp > n2.exp)
return n1 ;
else
return n2 ;
}
if(n1.exp > n2.exp) {
m = n1.mantissa + n2.mantissa / Math.pow(10, n1.exp - n2.exp) ;
e = n1.exp ;
}
else if (n1.exp < n2.exp){
m = n1.mantissa / Math.pow(10, n2.exp - n1.exp) + n2.mantissa ;
e = n2.exp ;
}
else {
m = n1.mantissa + n2.mantissa ;
e = n1.exp ;
}
if(m > 10.0) {
m/=10 ;
e++ ;
}
LargeNumber ln = new LargeNumber(m, e) ;
ln.normalize() ;
return ln ;
}
static public LargeNumber multiply(LargeNumber n1, LargeNumber n2) {
double m ;
int e ;
m = n1.mantissa * n2.mantissa ;
e = n1.exp + n2.exp ;
if(m > 10.0) {
m/=10.0 ;
e++ ;
}
LargeNumber ln = new LargeNumber(m, e) ;
ln.normalize() ;
return ln ;
}
public double val() {
return mantissa * Math.pow(10, exp) ;
}
/*
static public LargeNumber makeLargeNumberUsingExponent(double exponent) {
LargeNumber total = new LargeNumber(1.0, 0) ;
while(exponent > 300) {
exponent-=300 ;
double d = Math.pow(Math.E, 300) ;
LargeNumber ln = new LargeNumber(d) ;
total = LargeNumber.multiply(total, ln) ;
}
LargeNumber ln = new LargeNumber(Math.pow(Math.E, exponent)) ;
total = LargeNumber.multiply(total, ln) ;
total.normalize();
return total ;
}
*/
static public LargeNumber makeLargeNumberUsingExponent(double naturalExp) {
double floatExp = naturalExp * Math.log10(Math.E) ;
int intExp = (int) Math.floor(floatExp) ;
double mantissa = Math.pow(10.0, floatExp - intExp) ;
LargeNumber ln = new LargeNumber(mantissa, intExp) ;
ln.normalize() ;
return ln ;
}
public void setValueUsingExponent(double exponent) {
LargeNumber tmpLargeNumber = new LargeNumber(0.0, 0) ;
setValue(1.0, 0) ;
while(exponent > 300) {
exponent-=300 ;
double d = Math.pow(Math.E, 300) ;
tmpLargeNumber.setValue(d) ;
multiplyEquals(tmpLargeNumber) ;
}
tmpLargeNumber.setValue(Math.pow(Math.E, exponent)) ;
multiplyEquals(tmpLargeNumber) ;
}
static public double divide(LargeNumber ln1, LargeNumber ln2) {
double m = ln1.mantissa / ln2.mantissa ;
int e = ln1.exp - ln2.exp ;
if(e <= -300)
return 0.0 ;
else {
double d = m * Math.pow(10, e) ;
return d ;
}
}
public String toString() {
String s = "" ;
s = mantissa + " x E " + exp ;
return s ;
}
static public double log(LargeNumber ln) {
if(ln.mantissa == 0.0)
Prnt.endIt("Zero passed to LargeNumber.log") ;
double log = Math.log(ln.mantissa) + ln.exp * Math.log(10) ;
return log ;
}
static public double log10(LargeNumber ln) {
double value = 0.0 ;
if(ln.mantissa < 0)
Prnt.endIt("Attemping to take log10 of a negative number. Quiting.") ;
value = Math.log10(ln.mantissa) + ln.exp ;
return value ;
}
private void normalize() {
if(mantissa >= 1.0 && mantissa < 10.0)
return ;
double exp_of_mantissa = Math.log10(mantissa) ;
double floor_of_exp_of_mantissa = Math.floor(exp_of_mantissa) ;
mantissa = Math.pow(10.0, exp_of_mantissa - floor_of_exp_of_mantissa) ;
exp+=((int) floor_of_exp_of_mantissa) ;
}
public void plusEquals(LargeNumber largeNumber2) {
double m ;
int e ;
if(this.mantissa == 0.0) {
setValue(largeNumber2) ;
return ;
}
else if(largeNumber2.mantissa == 0.0)
return ;
if(Math.abs(this.exp - largeNumber2.exp) > 300 && this.mantissa != 0.0 && largeNumber2.mantissa != 0.0) {
//Prn.prn("The difference between the exponentials is more than 300. n1 = " + this + " and n2 = " + largeNumber2) ;
if(this.exp > largeNumber2.exp)
return ;
else {
setValue(largeNumber2) ;
return ;
}
}
if(this.exp > largeNumber2.exp) {
m = this.mantissa + largeNumber2.mantissa / Math.pow(10, this.exp - largeNumber2.exp) ;
e = this.exp ;
}
else if (this.exp < largeNumber2.exp){
m = this.mantissa / Math.pow(10, largeNumber2.exp - this.exp) + largeNumber2.mantissa ;
e = largeNumber2.exp ;
}
else {
m = this.mantissa + largeNumber2.mantissa ;
e = this.exp ;
}
if(m > 10.0) {
m/=10 ;
e++ ;
}
setValue(m,e) ;
normalize() ;
}
public void multiplyEquals(LargeNumber largeNumber2) {
mantissa*= largeNumber2.mantissa ;
exp+= largeNumber2.exp ;
if(mantissa > 10.0) {
mantissa/=10.0 ;
exp++ ;
}
normalize() ;
}
}