/* (c) Hundredsoft Corporation 2010-2012 All rights reserved.
Ldouble.h - VC 拡張倍精度クラス
*/
#ifndef LDOUBLE_INCLUDED
#define LDOUBLE_INCLUDED
#include
typedef struct {
unsigned char d[16];
} LONG_DOUBLE_STR, *LPLONG_DOUBLE_STR;
extern "C" void Ldouble_init(void);
extern "C" double LdoubleToDouble(LONG_DOUBLE_STR* m);
extern "C" void Ldouble_int64(LONG_DOUBLE_STR* m, __int64* v);
extern "C" void Ldouble_int(LONG_DOUBLE_STR* m, int* v);
extern "C" void Ldouble_double(LONG_DOUBLE_STR* m, double* v);
extern "C" void Ldouble_plus_eq(LONG_DOUBLE_STR* m, LONG_DOUBLE_STR* v);
extern "C" void Ldouble_minus_eq(LONG_DOUBLE_STR* m, LONG_DOUBLE_STR* v);
extern "C" void Ldouble_mul_eq(LONG_DOUBLE_STR* m, LONG_DOUBLE_STR* v);
extern "C" void Ldouble_div_eq(LONG_DOUBLE_STR* m, LONG_DOUBLE_STR* v);
extern "C" void Ldouble_rem_eq(LONG_DOUBLE_STR* m, LONG_DOUBLE_STR* v);
extern "C" void Ldouble_comp(LONG_DOUBLE_STR* m, LONG_DOUBLE_STR* v, int* sts);
extern "C" void Ldouble_frndint(LONG_DOUBLE_STR* m);
extern "C" void Ldouble_frnddec(LONG_DOUBLE_STR* m);
extern "C" void Ldouble_sin(LONG_DOUBLE_STR* m);
extern "C" void Ldouble_cos(LONG_DOUBLE_STR* m);
extern "C" void Ldouble_sincos(LONG_DOUBLE_STR* m, LONG_DOUBLE_STR* v);
extern "C" void Ldouble_tan(LONG_DOUBLE_STR* m);
extern "C" void Ldouble_atan(LONG_DOUBLE_STR* m);
extern "C" void Ldouble_atan2(LONG_DOUBLE_STR* m, LONG_DOUBLE_STR* v);
extern "C" void Ldouble_sqrt(LONG_DOUBLE_STR* m);
extern "C" void Ldouble_pi(LONG_DOUBLE_STR* m);
extern "C" void Ldouble_log(LONG_DOUBLE_STR* m);
extern "C" void Ldouble_log10(LONG_DOUBLE_STR* m);
extern "C" void Ldouble_exp(LONG_DOUBLE_STR* m, int* sign);
extern "C" void Ldouble_pow(LONG_DOUBLE_STR* m, LONG_DOUBLE_STR* v, int* sign);
class Ldouble
{
public:
Ldouble() {
memset(&m_data, 0, sizeof(m_data));
}
virtual ~Ldouble(){}
Ldouble(const Ldouble& v) {
if (this != &v){
memcpy(&m_data, &v.m_data, sizeof(m_data));
}
}
Ldouble(const __int64& v) {
Ldouble_int64(&m_data, (__int64*)&v);
}
Ldouble(const unsigned __int64& v) {
__int64 t = 0x8000000000000000;
int i;
for (i=63; i>=0; i--, t>>=1){
if (v & t) break;
}
if (i < 0){
memset(&m_data, 0, sizeof(m_data));
}else{
t = v;
t <<= 63-i; // 仮数部
int ex = i + 16383; // 指数部
memcpy(&m_data, &t, sizeof(__int64));
*(int*)&m_data.d[8] = ex;
}
}
Ldouble(const int& v) {
__int64 i = v;
Ldouble_int64(&m_data, (__int64*)&i);
}
Ldouble(const unsigned int& v) {
__int64 i = v;
Ldouble_int64(&m_data, (__int64*)&i);
}
Ldouble(const short& v) {
__int64 i = v;
Ldouble_int64(&m_data, (__int64*)&i);
}
Ldouble(const unsigned short& v) {
__int64 i = v;
Ldouble_int64(&m_data, (__int64*)&i);
}
Ldouble(const char& v) {
__int64 i = v;
Ldouble_int64(&m_data, (__int64*)&i);
}
Ldouble(const unsigned char& v) {
__int64 i = v;
Ldouble_int64(&m_data, (__int64*)&i);
}
Ldouble(const double& v) {
Ldouble_double(&m_data, (double*)&v);
}
Ldouble& operator=(const Ldouble& v){
if (this != &v){
memcpy(&m_data, &v.m_data, sizeof(m_data));
}
return *this;
}
// Unary -
Ldouble operator-(){
Ldouble v = *this;
v.m_data.d[9] ^= 0x80;
return v;
}
// Binary operator +=, -=, *=, /=
Ldouble& operator+=(const Ldouble& v){
Ldouble_plus_eq(&m_data, (LPLONG_DOUBLE_STR)&v.m_data);
return *this;
}
Ldouble& operator-=(const Ldouble& v){
Ldouble_minus_eq(&m_data, (LPLONG_DOUBLE_STR)&v.m_data);
return *this;
}
Ldouble& operator*=(const Ldouble& v){
Ldouble_mul_eq(&m_data, (LPLONG_DOUBLE_STR)&v.m_data);
return *this;
}
Ldouble& operator/=(const Ldouble& v){
Ldouble_div_eq(&m_data, (LPLONG_DOUBLE_STR)&v.m_data);
return *this;
}
Ldouble& operator%=(const Ldouble& v){
Ldouble_rem_eq(&m_data, (LPLONG_DOUBLE_STR)&v.m_data);
return *this;
}
// compare
// this < v: -
// this == v: 0
// this > v: +
int comp(const Ldouble& v) const{
int sts;
Ldouble_comp((LPLONG_DOUBLE_STR)&m_data, (LPLONG_DOUBLE_STR)&v.m_data, &sts);
return ((sts & 0x4100) - 1) ^ 0x3fff;
}
bool operator==(const Ldouble& v) const{
return (comp(v) == 0);
}
bool operator!=(const Ldouble& v) const{
return (comp(v) != 0);
}
bool operator<(const Ldouble& v) const{
return (comp(v) < 0);
}
bool operator<=(const Ldouble& v) const{
return (comp(v) <= 0);
}
bool operator>(const Ldouble& v) const{
return (comp(v) > 0);
}
bool operator>=(const Ldouble& v) const{
return (comp(v) >= 0);
}
bool operator==(const double& v) const{
return (comp(v) == 0);
}
bool operator!=(const double& v) const{
return (comp(v) != 0);
}
bool operator<(const double& v) const{
return (comp(v) < 0);
}
bool operator<=(const double& v) const{
return (comp(v) <= 0);
}
bool operator>(const double& v) const{
return (comp(v) > 0);
}
bool operator>=(const double& v) const{
return (comp(v) >= 0);
}
// cast
operator double() const{
return LdoubleToDouble((LPLONG_DOUBLE_STR)&m_data);
}
//friend Binary operator +,-,*,/
friend const Ldouble operator+(const Ldouble&a, const Ldouble&b){
Ldouble p(a);
p += b;
return p;
}
friend const Ldouble operator+(const Ldouble&a, const double&b){
Ldouble p(a);
p += (Ldouble)b;
return p;
}
friend const Ldouble operator+(const double&a, const Ldouble&b){
Ldouble p(a);
p += b;
return p;
}
friend const Ldouble operator-(const Ldouble&a, const Ldouble&b){
Ldouble p(a);
p -= b;
return p;
}
friend const Ldouble operator-(const Ldouble&a, const double&b){
Ldouble p(a);
p -= (Ldouble)b;
return p;
}
friend const Ldouble operator-(const double&a, const Ldouble&b){
Ldouble p(a);
p -= b;
return p;
}
friend const Ldouble operator*(const Ldouble&a, const Ldouble&b){
Ldouble p(a);
p *= b;
return p;
}
friend const Ldouble operator*(const Ldouble&a, const double&b){
Ldouble p(a);
p *= (Ldouble)b;
return p;
}
friend const Ldouble operator*(const double&a, const Ldouble&b){
Ldouble p(a);
p *= b;
return p;
}
friend const Ldouble operator/(const Ldouble&a, const Ldouble&b){
Ldouble p(a);
p /= b;
return p;
}
friend const Ldouble operator/(const Ldouble&a, const double&b){
Ldouble p(a);
p /= (Ldouble)b;
return p;
}
friend const Ldouble operator/(const double&a, const Ldouble&b){
Ldouble p(a);
p /= b;
return p;
}
friend const Ldouble operator%(const Ldouble&a, const Ldouble&b){
Ldouble p(a);
p %= b;
return p;
}
friend const Ldouble operator%(const Ldouble&a, const double&b){
Ldouble p(a);
p %= (Ldouble)b;
return p;
}
friend const Ldouble operator%(const double&a, const Ldouble&b){
Ldouble p(a);
p %= b;
return p;
}
LONG_DOUBLE_STR m_data;
};
namespace LD {
Ldouble abs(const Ldouble& s){
Ldouble v(s);
v.m_data.d[9] &= 0x7f;
return v;
}
Ldouble rndint(const Ldouble& s){
Ldouble v(s);
Ldouble_frndint(&v.m_data);
return v;
}
Ldouble rnddec(const Ldouble& s){
Ldouble v(s);
Ldouble_frnddec(&v.m_data);
return v;
}
Ldouble sin(const Ldouble& s){
Ldouble v(s);
Ldouble_sin(&v.m_data);
return v;
}
Ldouble cos(const Ldouble& s){
Ldouble v(s);
Ldouble_cos(&v.m_data);
return v;
}
void sincos(const Ldouble& s, Ldouble& sin, Ldouble& cos){
sin = s;
Ldouble_sincos(&sin.m_data, &cos.m_data);
}
Ldouble tan(const Ldouble& s){
Ldouble v(s);
Ldouble_tan(&v.m_data);
return v;
}
Ldouble atan(const Ldouble& s){
Ldouble v(s);
Ldouble_atan(&v.m_data);
return v;
}
Ldouble atan2(const Ldouble& x, const Ldouble& y){
Ldouble v(y);
Ldouble_atan2((LPLONG_DOUBLE_STR)&x.m_data, (LPLONG_DOUBLE_STR)&v.m_data);
return v;
}
Ldouble sqrt(const Ldouble& s){
Ldouble v(s);
Ldouble_sqrt(&v.m_data);
return v;
}
Ldouble pi(){
Ldouble v;
Ldouble_pi(&v.m_data);
return v;
}
Ldouble log(const Ldouble& s){
Ldouble v(s);
Ldouble_log(&v.m_data);
return v;
}
Ldouble log10(const Ldouble& s){
Ldouble v(s);
Ldouble_log10(&v.m_data);
return v;
}
Ldouble exp(const Ldouble& s){
Ldouble v(s);
LPLONG_DOUBLE_STR m = &v.m_data;
int sign = ((m->d[9] & 0x80) != 0) ? 1 : 0;
m->d[9] &= 0x7f;
Ldouble_exp(&v.m_data, &sign);
return v;
}
Ldouble pow(const Ldouble& x, const Ldouble& y){
Ldouble u(x),v(y);
LPLONG_DOUBLE_STR mx = &u.m_data;
LPLONG_DOUBLE_STR m = &v.m_data;
int xsign = ((mx->d[9] & 0x80) != 0) ? 1 : 0;
int ysign = ((m->d[9] & 0x80) != 0) ? 1 : 0;
if (xsign){
int ny = (int)v;
Ldouble t = ny;
if (t != y){
throw "Invalid value.";
}
xsign = (ny & 1) ? 1 : 0;
}
mx->d[9] &= 0x7f;
m->d[9] &= 0x7f;
Ldouble_pow(mx, m, &ysign);
if (xsign){
m->d[9] |= 0x80;
}
return v;
}
} // end of namespace
#endif