mirror of
http://43.156.76.180:8026/YuuMJ/EukPhylo.git
synced 2025-12-28 03:10:26 +08:00
320 lines
8.5 KiB
C++
320 lines
8.5 KiB
C++
#ifndef __DOUBLE_REP_H
|
|
#define __DOUBLE_REP_H
|
|
|
|
#ifdef DOUBLEREP
|
|
#include "definitions.h"
|
|
|
|
#include <iostream>
|
|
#include <cmath>
|
|
#include <cstdlib>
|
|
using namespace std;
|
|
|
|
/* doubleRepMantisa: enables working with much larger or smaller numbers than normally possible
|
|
by the regular double representation
|
|
* Representation of a double x as x=_mantissa*2^_expon
|
|
Note: Base is 2!!
|
|
*/
|
|
|
|
class doubleRepMantisa{
|
|
public:
|
|
|
|
doubleRepMantisa(){};
|
|
explicit doubleRepMantisa(MDOUBLE mantissa, int expon);
|
|
doubleRepMantisa(MDOUBLE a);
|
|
doubleRepMantisa(const doubleRepMantisa& other);
|
|
doubleRepMantisa* clone() {return new doubleRepMantisa(*this);}
|
|
void output(ostream &out) const{ out<<_mantissa<<string(" * 2^")<<_expon;}
|
|
// void output0x(ostream &out) const{ double e0x=_expon*0.3010299956639; // log_10(2)
|
|
// int e=(int)(trunc(e0x))-1;
|
|
// double m=_mantissa*pow(10,e0x-e);
|
|
// out<<m;
|
|
// if (e<0)
|
|
// out<<"e"<<e;
|
|
// else
|
|
// out<<"e+"<<e;
|
|
//}
|
|
void outputn(ostream &out) { out<<_mantissa<<string(" * 2^")<<_expon<<endl;}
|
|
|
|
friend MDOUBLE convert(const doubleRepMantisa& a);
|
|
inline doubleRepMantisa& operator=(const doubleRepMantisa& a);
|
|
inline doubleRepMantisa& operator+=(doubleRepMantisa a);
|
|
inline doubleRepMantisa& operator++();
|
|
inline doubleRepMantisa operator++(int);
|
|
inline doubleRepMantisa& operator--();
|
|
inline doubleRepMantisa operator--(int);
|
|
friend inline doubleRepMantisa operator+(const doubleRepMantisa& a, const doubleRepMantisa& b);
|
|
inline doubleRepMantisa& operator-=(const doubleRepMantisa& a);
|
|
friend inline doubleRepMantisa operator-(const doubleRepMantisa& a, const doubleRepMantisa& b);
|
|
inline doubleRepMantisa& operator*=(const doubleRepMantisa& a);
|
|
friend inline doubleRepMantisa operator*(const doubleRepMantisa& a, const doubleRepMantisa& b);
|
|
inline doubleRepMantisa& operator/=(const doubleRepMantisa& a);
|
|
friend inline doubleRepMantisa operator/(const doubleRepMantisa& a, const doubleRepMantisa& b);
|
|
|
|
friend inline bool operator==(const doubleRepMantisa& a, const doubleRepMantisa& b);
|
|
friend inline bool operator!=(const doubleRepMantisa& a, const doubleRepMantisa& b);
|
|
friend inline bool operator<(const doubleRepMantisa& a, const doubleRepMantisa& b);
|
|
friend inline bool operator<=(const doubleRepMantisa& a, const doubleRepMantisa& b);
|
|
friend inline bool operator>(const doubleRepMantisa& a, const doubleRepMantisa& b);
|
|
friend inline bool operator>=(const doubleRepMantisa& a, const doubleRepMantisa& b);
|
|
friend inline doubleRepMantisa abs(const doubleRepMantisa& d);
|
|
|
|
|
|
const MDOUBLE d_log() const;
|
|
// friend ostream& operator<<(ostream &out, const doubleRepMantisa& a);
|
|
|
|
const MDOUBLE mantissa() const {return _mantissa;}
|
|
const int expon() const {return _expon;}
|
|
|
|
private:
|
|
void fixParams();
|
|
|
|
|
|
private:
|
|
MDOUBLE _mantissa;
|
|
int _expon;
|
|
};
|
|
|
|
MDOUBLE convert(const doubleRepMantisa& a); //declaration of this function to be implemented cpp
|
|
|
|
inline doubleRepMantisa& doubleRepMantisa::operator=(const doubleRepMantisa& a){
|
|
_mantissa=a.mantissa();
|
|
_expon=a.expon();
|
|
return *this;
|
|
}
|
|
|
|
|
|
inline doubleRepMantisa& doubleRepMantisa::operator++() {
|
|
return (*this)+=1;
|
|
}
|
|
|
|
// matan:
|
|
inline doubleRepMantisa doubleRepMantisa::operator++(int) {
|
|
doubleRepMantisa ans = *this;
|
|
++(*this);
|
|
return ans;
|
|
}
|
|
|
|
// matan:
|
|
inline doubleRepMantisa& doubleRepMantisa::operator--() {
|
|
return (*this)-=1;
|
|
}
|
|
|
|
// matan:
|
|
inline doubleRepMantisa doubleRepMantisa::operator--(int) {
|
|
doubleRepMantisa ans = *this;
|
|
--(*this);
|
|
return ans;
|
|
}
|
|
|
|
|
|
// Original version by Adi Stern
|
|
inline doubleRepMantisa& doubleRepMantisa::operator+=(doubleRepMantisa a){
|
|
//ensuring that (*this) is bigger than 'a' for sake of convenience
|
|
if (a.expon()>_expon || ((a.expon()==_expon) && (a.mantissa()>_mantissa))){
|
|
MDOUBLE tmpMant=0.0; int tmpExp=0;
|
|
tmpMant=_mantissa;
|
|
tmpExp=_expon;
|
|
_mantissa=a.mantissa();
|
|
a._mantissa=tmpMant;
|
|
tmpExp=_expon;
|
|
_expon=a.expon();
|
|
a._expon=tmpExp;
|
|
}
|
|
if (a.mantissa()==0)
|
|
return *this;
|
|
if (_mantissa==0){
|
|
_mantissa=a.mantissa();
|
|
_expon=a.expon();
|
|
return *this;
|
|
}
|
|
int exp_dif = _expon-a.expon();
|
|
if (abs(exp_dif)>51){ //limit of epsilon difference
|
|
return *this;
|
|
}
|
|
_mantissa+=a.mantissa()*pow(2.0,(a.expon()-_expon)*1.0);
|
|
fixParams();
|
|
return *this;
|
|
}
|
|
|
|
inline doubleRepMantisa operator+(const doubleRepMantisa& a, const doubleRepMantisa& b){
|
|
doubleRepMantisa temp(a);
|
|
temp+=b;
|
|
return temp;
|
|
}
|
|
|
|
inline doubleRepMantisa& doubleRepMantisa::operator-=(const doubleRepMantisa& a){
|
|
doubleRepMantisa b(-a.mantissa(),a.expon());
|
|
doubleRepMantisa me(_mantissa,_expon);
|
|
me+=b;
|
|
_mantissa=me.mantissa();
|
|
_expon=me.expon();
|
|
return *this;
|
|
}
|
|
|
|
inline doubleRepMantisa operator-(const doubleRepMantisa& a, const doubleRepMantisa& b){
|
|
doubleRepMantisa temp(a);
|
|
temp-=b;
|
|
return temp;
|
|
}
|
|
|
|
inline doubleRepMantisa operator-(const doubleRepMantisa& a) {
|
|
return doubleRepMantisa(0) - a;
|
|
}
|
|
|
|
inline doubleRepMantisa& doubleRepMantisa::operator*=(const doubleRepMantisa& a){
|
|
_mantissa*=a.mantissa();
|
|
_expon+=a.expon();
|
|
fixParams();
|
|
return *this;
|
|
}
|
|
|
|
inline doubleRepMantisa operator*(const doubleRepMantisa& a, const doubleRepMantisa& b){
|
|
doubleRepMantisa temp(a);
|
|
temp*=b;
|
|
return temp;
|
|
}
|
|
|
|
inline doubleRepMantisa& doubleRepMantisa::operator/=(const doubleRepMantisa& a){
|
|
_mantissa/=a.mantissa();
|
|
_expon-=a.expon();
|
|
fixParams();
|
|
return *this;
|
|
}
|
|
|
|
inline doubleRepMantisa operator/(const doubleRepMantisa& a, const doubleRepMantisa& b){
|
|
doubleRepMantisa temp(a);
|
|
temp/=b;
|
|
return temp;
|
|
}
|
|
|
|
/************************
|
|
* Comparison operators *
|
|
************************/
|
|
inline bool operator==(const doubleRepMantisa& a, const doubleRepMantisa& b){
|
|
return (a._mantissa==b._mantissa && a._expon==b._expon);
|
|
}
|
|
inline bool operator!=(const doubleRepMantisa& a, const doubleRepMantisa& b){
|
|
return !(a==b);
|
|
}
|
|
|
|
inline bool operator<(const doubleRepMantisa& a, const doubleRepMantisa& b){
|
|
// if the numbers have opposite signs
|
|
if (a._mantissa*b._mantissa<0.0){
|
|
if (a._mantissa<b._mantissa) {return true;}
|
|
else {return false;}
|
|
}
|
|
// if the expon values are different
|
|
if (a._expon!=b._expon) {
|
|
// special case where one number is zero
|
|
if (a._mantissa == 0.0) {
|
|
if (b._mantissa > 0.0) {return true;}
|
|
else {return false;}
|
|
}
|
|
if (b._mantissa == 0.0) {
|
|
if (a._mantissa < 0.0) {return true;}
|
|
else {return false;}
|
|
}
|
|
|
|
if (a._expon<b._expon) {
|
|
if (a._mantissa > 0.0) {return true;}
|
|
else {return false;}
|
|
} else {
|
|
if (a._mantissa < 0.0) {return true;}
|
|
else {return false;}
|
|
}
|
|
// expon values are identical
|
|
} else {
|
|
return (a._mantissa < b._mantissa);
|
|
}
|
|
}
|
|
|
|
inline bool operator>(const doubleRepMantisa& a, const doubleRepMantisa& b){
|
|
// if the numbers have opposite signs
|
|
if (a._mantissa*b._mantissa<0.0){
|
|
if (a._mantissa>b._mantissa) {return true;}
|
|
else {return false;}
|
|
}
|
|
// if the expon values are different
|
|
if (a._expon!=b._expon) {
|
|
// special case where one number is zero
|
|
if (a._mantissa == 0.0) {
|
|
if (b._mantissa < 0.0) {return true;}
|
|
else {return false;}
|
|
}
|
|
if (b._mantissa == 0.0) {
|
|
if (a._mantissa > 0.0) {return true;}
|
|
else {return false;}
|
|
}
|
|
|
|
if (a._expon>b._expon) {
|
|
if (a._mantissa > 0.0) {return true;}
|
|
else {return false;}
|
|
} else {
|
|
if (a._mantissa < 0.0) {return true;}
|
|
else {return false;}
|
|
}
|
|
// expon values are identical
|
|
} else {
|
|
return (a._mantissa > b._mantissa);
|
|
}
|
|
}
|
|
|
|
inline bool operator<=(const doubleRepMantisa& a, const doubleRepMantisa& b){
|
|
return !(a>b);
|
|
}
|
|
|
|
inline bool operator>=(const doubleRepMantisa& a, const doubleRepMantisa& b){
|
|
return !(a<b);
|
|
}
|
|
|
|
|
|
|
|
|
|
ostream& operator<<(ostream &out, const doubleRepMantisa& a);
|
|
istream& operator>>(istream &in, doubleRepMantisa& a);
|
|
|
|
inline MDOUBLE log(const doubleRepMantisa& d) {return d.d_log();}
|
|
|
|
inline ostream &operator<<(ostream &out, const VdoubleRepMantisa &v){
|
|
for (int j=0;j<v.size();++j)
|
|
out<< v[j]<<" ";
|
|
out <<endl;
|
|
return(out);
|
|
}
|
|
|
|
inline ostream &operator<<(ostream &out, const VVdoubleRepMantisa &m){
|
|
for (int i=0;i<m.size();++i)
|
|
out<<m[i];
|
|
out <<endl;
|
|
return(out);
|
|
}
|
|
|
|
inline doubleRepMantisa pow(const doubleRepMantisa& d1, const doubleRepMantisa& d2) {
|
|
return doubleRepMantisa(pow(convert(d1), convert(d2)));
|
|
}
|
|
|
|
inline doubleRepMantisa abs(const doubleRepMantisa& d) {
|
|
return doubleRepMantisa(abs(d._mantissa), d._expon);
|
|
}
|
|
|
|
inline doubleRepMantisa fabs(const doubleRepMantisa& d) {
|
|
return abs(d);
|
|
}
|
|
|
|
inline doubleRepMantisa exp(const doubleRepMantisa& d) {
|
|
return doubleRepMantisa(exp(convert(d)));
|
|
}
|
|
|
|
inline doubleRepMantisa sqrt(const doubleRepMantisa& d) {
|
|
return doubleRepMantisa(sqrt(convert(d)));
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//inline const MDOUBLE convert (const MDOUBLE d) const {return(d);}
|
|
|
|
#endif
|
|
#endif
|