00001 00002 // MathCore = a WYSIWYG equation editor + a powerful math engine // 00003 // Copyright (C) 2003 by Francesco Montorsi // 00004 // // 00005 // This library is free software; you can redistribute it and/or // 00006 // modify it under the terms of the GNU Lesser General Public // 00007 // License as published by the Free Software Foundation; either // 00008 // version 2.1 of the License, or (at your option) any later // 00009 // version. // 00010 // // 00011 // This library is distributed in the hope that it will be useful, // 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of // 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // 00014 // GNU Lesser General Public License for more details. // 00015 // // 00016 // You should have received a copy of the GNU Lesser General Public // 00017 // License along with this program; if not, write to the Free // 00018 // Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, // 00019 // MA 02111-1307, USA. // 00020 // // 00021 // For any comment, suggestion or feature request, please contact // 00022 // the administrator of the project at frm@users.sourceforge.net // 00023 // // 00030 00031 00032 00033 #ifndef VALUE_H 00034 #define VALUE_H 00035 00036 // optimization for GCC compiler 00037 #ifdef __GNUG__ 00038 #pragma interface "Value.h" 00039 #endif 00040 00041 // required includes 00042 #include "mc/Setup.h" 00043 #include <math.h> // In any case we'll need the standard pow() since GMP 00044 // does not have a mpf_pow(mpf_t rop, mpf_t base, mpf_t exp) 00045 00046 #ifdef mcUSE_GMP 00047 00048 #include <gmp.h> // The main include of the GNU Multiple Precision library 00049 00050 #else 00051 00052 // DUMMY GMP-LIKE INTERFACE (only for debugging) 00053 // --------------------------------------------- 00054 typedef struct { double val; } __mpf_struct; 00055 #define __mpq_struct __mpf_struct 00056 #define __mpz_struct __mpf_struct 00057 #define mp_exp_t int 00058 00059 typedef __mpz_struct* mpz_t; 00060 typedef const __mpz_struct* mpz_src; 00061 typedef __mpq_struct* mpq_t; 00062 typedef const __mpq_struct* mpq_src; 00063 typedef __mpf_struct* mpf_t; 00064 typedef const __mpq_struct* mpf_src; 00065 00066 00067 // MPF functions 00068 00069 static unsigned long mpf_get_ui(mpf_src op) { return op.val; } 00070 static void mpf_set_z(mpf_t op, mpz_src t) { op.val = t.val; } 00071 static void mpf_set_q(mpf_t op, mpq_src t) { op.val = t.val; } 00072 static void mpf_init(mpf_t op) { /*op = new __mpf_struct;*/ op.val = 0; } 00073 static void mpf_clear(mpf_t op) { /*delete op;*/ op.val = 0; } 00074 static void mpf_set(mpf_t op, mpf_src t) { op.val = t.val; } 00075 static void mpf_set_ui(mpf_t op, unsigned long newval) { op.val = newval; } 00076 static void mpf_set_str(mpf_t op, const char *str, int) { op.val = atoi(str); } 00077 static void mpf_abs(mpf_t op, mpf_src t) { op.val = abs(t.val); } 00078 static void mpf_pow_ui(mpf_t op, mpf_src base, unsigned long exp) { op.val = pow(base.val, exp); } 00079 static void mpf_floor(mpf_t op, mpf_src t) { op.val = floor(t.val); } 00080 static void mpf_ceil(mpf_t op, mpf_src t) { op.val = ceil(t.val); } 00081 static void mpf_trunc(mpf_t op, mpf_src t) { op.val = ceil(t.val); } 00082 static void mpf_add_ui(mpf_t op, mpf_src t, unsigned long add) { op.val = t.val + add; } 00083 static void mpf_sub_ui(mpf_t op, mpf_src t, unsigned long add) { op.val = t.val - add; } 00084 static void mpf_add(mpf_t op, mpf_src t, mpf_src add) { op.val = t.val + add.val; } 00085 static void mpf_sub(mpf_t op, mpf_src t, mpf_src add) { op.val = t.val - add.val; } 00086 static void mpf_mul(mpf_t op, mpf_src t, mpf_src add) { op.val = t.val * add.val; } 00087 static void mpf_div(mpf_t op, mpf_src t, mpf_src add) { op.val = t.val / add.val; } 00088 static void mpf_set_d(mpf_t op, double t) { op.val = t; } 00089 static double mpf_get_d(mpf_src op) { return op.val; } 00090 static int mpf_integer_p(mpf_src op) { return ceil(op.val) == floor(op.val); } 00091 00092 static int mpf_cmp_d(mpf_src op, double op2) { if (op.val > op2) return 1; 00093 if (op.val == op2) return 0; 00094 return -1; } 00095 static int mpf_cmp_si(mpf_src op, long op2) { return mpf_cmp_d(op, (double)op2); } 00096 static int mpf_cmp(mpf_src op, mpf_src op2) { return mpf_cmp_d(op, op2.val); } 00097 00098 static char *mpf_get_str(char *str, int *exp, int base, int digits, mpf_src op) { return wxT(""); } 00099 00100 static void mp_set_memory_functions ( 00101 static void *(*alloc_func_ptr) (size_t), 00102 static void *(*realloc_func_ptr) (static void *, size_t, size_t), 00103 static void (*free_func_ptr) (static void *, size_t)) {} 00104 00105 00106 00107 // MPZ functions 00108 00109 #define mpz_init mpf_init 00110 #define mpz_clear mpf_clear 00111 #define mpz_set mpf_set 00112 #define mpz_set_ui mpf_set_ui 00113 #define mpz_get_ui mpf_get_ui 00114 #define mpz_set_str mpf_set_str 00115 #define mpz_abs mpf_abs 00116 #define mpz_pow_ui mpf_pow_ui 00117 00118 static void mpz_gcd(mpz_t res, mpz_src, mpz_src) { res.val = 0; } 00119 static void mpz_lcm(mpz_t res, mpz_src, mpz_src) { res.val = 0; } 00120 static void mpz_set_q(mpz_t res, mpq_src d) { res.val = d.val; } 00121 static void mpz_set_f(mpz_t res, mpf_src d) { res.val = d.val; } 00122 static int mpz_sizeinbase(mpf_src d, int) { return 10; } 00123 static char *mpz_get_str(char *str, int, mpz_src op) { return wxT(""); } 00124 00125 00126 00127 // MPQ functions 00128 00129 #define mpq_init mpf_init 00130 #define mpq_clear mpf_clear 00131 #define mpq_set mpf_set 00132 #define mpq_get_ui mpf_get_ui 00133 #define mpq_set_str mpf_set_str 00134 #define mpq_abs mpf_abs 00135 00136 static void mpq_get_den(mpz_t op, mpq_src) { op.val = 1; } 00137 static void mpq_get_num(mpz_t op, mpq_src t) { op.val = t.val; } 00138 static void mpq_set_d(mpq_t op, double d) { op.val = d; } 00139 static void mpq_set_z(mpq_t op, mpz_src d) { op.val = d.val; } 00140 static void mpq_set_f(mpq_t op, mpf_src d) { op.val = d.val; } 00141 static void mpq_canonicalize(mpz_t) {} 00142 static void mpq_set_ui(mpz_t op, unsigned long n, unsigned long d) { op.val = n/d; } 00143 static double mpq_get_d(mpq_src op) { return op.val; } 00144 00145 #endif 00146 00147 00148 00150 #define mcVALUE_DEFAULTPRECISION 30 00151 00153 #define mcVALUE_SMARTSTR_THRESHOLD 10 00154 00155 #if wxUSE_UNICODE 00156 #define WX2GMP(x) (wxString(x).mb_str(wxConvUTF8).data()) 00157 #else 00158 #define WX2GMP(x) (wxString(x).mb_str(wxConvUTF8)) 00159 #endif 00160 00161 #define GMP2WX(x) (wxString(x, wxConvUTF8)) 00162 00163 00164 00165 // these will be defined later 00166 class mcIntegerValue; 00167 class mcRationalValue; 00168 class mcRealValue; 00169 class mcComplexValue; 00170 00171 00175 void *mcGMPAlloc(size_t n); 00176 00180 void *mcGMPRealloc(void *p, size_t oldsz, size_t newsz); 00181 00184 void mcGMPFree(void *, size_t); 00185 00186 00187 00188 00191 00194 #define mcVALUE_MASK 0xFFFF0000 00195 00196 #define mcVALUE_NAN_FLAG 0x000F 00197 #define mcVALUE_POSINF_FLAG 0x00F0 00198 #define mcVALUE_NEGINF_FLAG 0x0F00 00199 00203 #define mcVALUE_DEFINE_GMP_STRUCTWRAPPER(name, base) \ 00204 struct name : base { \ 00205 wxUint32 flags; \ 00206 \ 00207 void SetRefCount(wxUint16 n) \ 00208 { flags = (n & ~mcVALUE_MASK) | (GetFlags()<<16); } \ 00209 wxUint16 GetRefCount() const \ 00210 { return (wxUint16)(flags & ~mcVALUE_MASK); } \ 00211 void SetFlags(wxUint16 n) \ 00212 { flags = (((int)n) << 16) | GetRefCount(); } \ 00213 wxUint16 GetFlags() const \ 00214 { return (wxUint16)(flags >> 16); } \ 00215 }; 00216 00217 mcVALUE_DEFINE_GMP_STRUCTWRAPPER(mcMPF, __mpf_struct); 00218 mcVALUE_DEFINE_GMP_STRUCTWRAPPER(mcMPQ, __mpq_struct); 00219 mcVALUE_DEFINE_GMP_STRUCTWRAPPER(mcMPZ, __mpz_struct); 00220 00222 00223 00224 00229 00233 #define mcVALUE_DEFINE_INTERNALS(x, fncprefix) \ 00234 void InternalInit(int flags = 0) { \ 00235 mp = new x; fncprefix##_init(mp); \ 00236 mp->SetRefCount((wxUint16)1); \ 00237 mp->SetFlags((wxInt16)flags); } \ 00238 void InternalDestroy() \ 00239 { fncprefix##_clear(mp); delete mp; } 00240 00243 #define mcVALUE_DEFINE_REFCOUNT(x, y) \ 00244 \ 00245 x *mp; \ 00246 \ 00247 void CopyMP(const x *n) { \ 00248 mcASSERT(mp != NULL, \ 00249 wxT("This object is not initialized")); \ 00250 y##_set(mp, n); /* DO NOT USE MP() !! */ \ 00251 mp->flags = n->flags; \ 00252 } \ 00253 \ 00254 \ 00255 void Ref(x *p) { \ 00256 mcASSERT(p->GetRefCount() > 0, \ 00257 wxT("This object cannot exist")); \ 00258 p->SetRefCount((wxUint16)(p->GetRefCount()+1)); \ 00259 } \ 00260 \ 00261 \ 00262 \ 00263 void Unref() { \ 00264 mcASSERT(mp->GetRefCount() > 0, \ 00265 wxT("This object cannot exist")); \ 00266 \ 00267 if (mp) \ 00268 m_nMaxValueSharing = mcMAX(m_nMaxValueSharing, \ 00269 mp->GetRefCount()); \ 00270 \ 00271 mp->SetRefCount((wxUint16)(mp->GetRefCount()-1)); \ 00272 if (mp->GetRefCount() == 0) \ 00273 InternalDestroy(); \ 00274 } 00275 00278 #define mcVALUE_DEFINE_INTERNAL_GETTERS(x) \ 00279 \ 00280 x *MP() { \ 00281 mcASSERT(mp->GetRefCount() > 0, \ 00282 wxT("This object cannot exist")); \ 00283 if (mp->GetRefCount() == 1) \ 00284 return mp; \ 00285 \ 00286 /* make a private instance copying the shared object */ \ 00287 x *old = mp; \ 00288 Unref(); \ 00289 InternalInit(); \ 00290 CopyMP(old); \ 00291 return mp; \ 00292 } \ 00293 \ 00294 \ 00295 \ 00296 const x *cMP() const { \ 00297 return mp; \ 00298 } 00299 00301 #define mcVALUE_DEFINE_SETGET_FLAGS() \ 00302 int GetFlags() const { return (int)cMP()->GetFlags(); } \ 00303 void SetFlags(int n) { MP()->SetFlags((wxInt16)n); } \ 00304 bool hasSameFlags(int n) const { return GetFlags() == n; } 00305 00307 #define mcVALUE_DEFINE_SETTERS(x, fncprefix) \ 00308 void SetLong(long n) { fncprefix##_set_si(MP(), n); } \ 00309 void SetStr(const wxString &str, int base = 10) \ 00310 { fncprefix##_set_str(MP(), WX2GMP(str), base); } 00311 00313 #define mcVALUE_DEFINE_GETTERS(x, fncprefix) \ 00314 long GetLong() const { return fncprefix##_get_ui(cMP()); } 00315 00319 #define mcVALUE_DEFINE_MISCELLANEOUS(rettype, fncprefix) \ 00320 rettype ChangeSign() \ 00321 { rettype ret; fncprefix##_neg(ret.MP(), cMP()); return ret; } 00322 00324 #define mcVALUE_DEFINE_GETSET(x, fncprefix) \ 00325 mcVALUE_DEFINE_SETGET_FLAGS() \ 00326 mcVALUE_DEFINE_GETTERS(x, fncprefix) \ 00327 mcVALUE_DEFINE_SETTERS(x, fncprefix) 00328 00329 #define mcVALUE_DEFINE_FLAGS_EQUAL_OPERATORS(y, fnc, z) \ 00330 bool operator==(y m) const {return (fnc(cMP(), z) == 0) && hasSameFlags(m.GetFlags());} \ 00331 bool operator!=(y m) const {return (fnc(cMP(), z) != 0) || !hasSameFlags(m.GetFlags());} 00332 00333 #define mcVALUE_DEFINE_NOFLAGS_EQUAL_OPERATORS(y, fnc, z) \ 00334 bool operator==(y m) const {return (fnc(cMP(), z) == 0);} \ 00335 bool operator!=(y m) const {return (fnc(cMP(), z) != 0);} 00336 00338 #define mcVALUE_DEFINE_NOFLAGS_GTLT_OPERATORS(y, fnc, z) \ 00339 bool operator<=(y m) const {return (fnc(cMP(), z) <= 0);} \ 00340 bool operator>=(y m) const {return (fnc(cMP(), z) >= 0);} \ 00341 bool operator<(y m) const {return (fnc(cMP(), z) < 0);} \ 00342 bool operator>(y m) const {return (fnc(cMP(), z) > 0);} 00343 00344 #define mcVALUE_DEFINE_NOFLAGSCOMPARISON_OPERATORS(y, fnc, z) \ 00345 mcVALUE_DEFINE_NOFLAGS_GTLT_OPERATORS(y, fnc, z) \ 00346 mcVALUE_DEFINE_NOFLAGS_EQUAL_OPERATORS(y, fnc, z) 00347 00348 #define mcVALUE_DEFINE_FLAGSCOMPARISON_OPERATORS(y, fnc, z) \ 00349 mcVALUE_DEFINE_NOFLAGS_GTLT_OPERATORS(y, fnc, z) \ 00350 mcVALUE_DEFINE_FLAGS_EQUAL_OPERATORS(y, fnc, z) 00351 00353 #define mcVALUE_DEFINE_ARITHMETIC_OPERATORS(rettype, x, y, fncprefix, z, w) \ 00354 friend rettype operator+(x a, y b) \ 00355 {rettype ret; fncprefix##_add(ret.MP(), z, w); return ret;} \ 00356 friend rettype operator-(x a, y b) \ 00357 {rettype ret; fncprefix##_sub(ret.MP(), z, w); return ret;} \ 00358 friend rettype operator*(x a, y b) \ 00359 {rettype ret; fncprefix##_mul(ret.MP(), z, w); return ret;} \ 00360 friend rettype operator/(x a, y b) \ 00361 {rettype ret; fncprefix##_div(ret.MP(), z, w); return ret;} 00362 00364 #define mcVALUE_DEFINE_UNARY_OPERATORS(rettype, x, fncprefix) \ 00365 rettype &operator=(const rettype &m) { Unref(); mp=m.mp; Ref(mp); return *this;} \ 00366 rettype &operator=(x &m) { mp=&m; Ref(mp); return *this;} \ 00367 rettype &operator=(const wxString &str) { SetStr(str); return *this;} \ 00368 rettype &operator=(int n) { SetInt(n); return *this;} \ 00369 rettype operator++() { fncprefix##_add_ui(MP(), cMP(), 1); return *this;} \ 00370 rettype operator--() { fncprefix##_sub_ui(MP(), cMP(), 1); return *this;} \ 00371 rettype &operator+=(const rettype &m) {*this = *this+m;return *this;} \ 00372 rettype &operator-=(const rettype &m) {*this = *this-m;return *this;} \ 00373 rettype &operator*=(const rettype &m) {*this = *this*m;return *this;} \ 00374 rettype &operator/=(const rettype &m) {*this = *this/m;return *this;} 00375 00377 #define mcVALUE_DEFINE_ALLOPERATORS(x, structname, y) \ 00378 mcVALUE_DEFINE_UNARY_OPERATORS(x, structname, y); \ 00379 \ 00380 mcVALUE_DEFINE_ARITHMETIC_OPERATORS(x, const x &, const x &, y, a.cMP(), b.cMP()); \ 00381 mcVALUE_DEFINE_ARITHMETIC_OPERATORS(x, const x &, long, y, a.cMP(), x(b).cMP()); \ 00382 mcVALUE_DEFINE_ARITHMETIC_OPERATORS(x, const x &, int, y, a.cMP(), x(b).cMP()); \ 00383 mcVALUE_DEFINE_ARITHMETIC_OPERATORS(x, long, const x &, y, x(a).cMP(), b.cMP()); \ 00384 mcVALUE_DEFINE_ARITHMETIC_OPERATORS(x, int, const x &, y, x(a).cMP(), b.cMP()); \ 00385 \ 00386 mcVALUE_DEFINE_FLAGSCOMPARISON_OPERATORS(const x &, __g##y##_cmp, m.cMP()); \ 00387 mcVALUE_DEFINE_NOFLAGSCOMPARISON_OPERATORS(long, __g##y##_cmp_si, m); \ 00388 mcVALUE_DEFINE_NOFLAGSCOMPARISON_OPERATORS(int, __g##y##_cmp_si, (long)m); \ 00389 mcVALUE_DEFINE_MISCELLANEOUS(x, y) 00390 00391 #define mcVALUE_DEFINE_DOUBLEOPERATORS(x, structname, y) \ 00392 mcVALUE_DEFINE_ARITHMETIC_OPERATORS(x, const x &, double, y, a.cMP(), x(b).cMP()); \ 00393 mcVALUE_DEFINE_ARITHMETIC_OPERATORS(x, double, const x &, y, x(a).cMP(), b.cMP()); \ 00394 mcVALUE_DEFINE_NOFLAGSCOMPARISON_OPERATORS(double, __g##y##_cmp_d, m) 00395 00396 00398 #define mcVALUE_DEFINE_COW(x, y) \ 00399 protected: \ 00400 mcVALUE_DEFINE_INTERNALS(x, y); \ 00401 mcVALUE_DEFINE_REFCOUNT(x, y); \ 00402 public: \ 00403 mcVALUE_DEFINE_INTERNAL_GETTERS(x) 00404 00406 #define mcVALUE_DEFINE_CONSTRUCTORS(x, y) \ 00407 x() { InternalInit(); } \ 00408 x(long n) { InternalInit(); SetLong(n); } \ 00409 x(int n) { InternalInit(); SetLong(n); } \ 00410 x(const wxString &str) { InternalInit(); SetStr(str); } \ 00411 x(y *m) { mp=m; Ref(mp); } \ 00412 x(const x &m) { mp=m.mp; Ref(mp); } \ 00413 virtual ~x() { Unref(); } 00414 00416 00417 00418 00419 00420 00423 class mcValue 00424 { 00425 public: 00426 00429 static int m_nMaxValueSharing; 00430 00431 public: 00432 mcValue() {} // cannot build anything since everything is declared in derived classes. 00433 virtual ~mcValue() {} 00434 00435 00438 static void Init(); 00439 00443 static void Cleanup(); 00444 00445 00446 public: // standard conversions 00447 00448 virtual void SetInt(int n) { SetLong(n); } 00449 virtual void SetLong(long n) = 0; 00450 virtual void SetStr(const wxString &str, int base = 10) = 0; 00451 00452 virtual long GetLong() const = 0; 00453 virtual int GetInt() const { return (int)GetLong(); } 00454 00455 operator int() const { return GetInt(); } 00456 operator long() const { return GetLong(); } 00457 #ifndef __BORLANDC__ 00458 operator unsigned long() { return (unsigned long)GetLong(); } 00459 #endif 00460 00474 virtual wxString GetStr() const = 0; 00475 00476 public: // miscellaneous functions 00477 00480 bool isValid() const { return !isNAN() & math_isFinite(); } 00481 00483 bool isNAN() const { return (GetFlags() & mcVALUE_NAN_FLAG) != 0; } 00484 00486 bool math_isFinite() const { return !isPosInf() & !isNegInf(); } 00487 00488 bool isPosInf() const { return (GetFlags() & mcVALUE_POSINF_FLAG) != 0; } 00489 bool isNegInf() const { return (GetFlags() & mcVALUE_NEGINF_FLAG) != 0; } 00490 00493 virtual bool isInteger() const = 0; 00494 00497 virtual int GetFlags() const = 0; 00498 00501 virtual void SetFlags(int n) = 0; 00502 00505 void math_AddFlag(int n) { SetFlags(n | GetFlags()); } 00506 }; 00507 00509 class mcIntegerValue : public mcValue 00510 { 00511 mcVALUE_DEFINE_COW(mcMPZ, mpz); 00512 00513 public: // static 00514 00515 static mcIntegerValue *pOne; 00516 static mcIntegerValue *pZero; 00517 static mcIntegerValue *pNAN; 00518 static mcIntegerValue *pPosInf; 00519 static mcIntegerValue *pNegInf; 00520 00521 public: 00522 mcVALUE_DEFINE_CONSTRUCTORS(mcIntegerValue, mcMPZ); 00523 mcIntegerValue(const mcRationalValue &m); 00524 mcIntegerValue(const mcRealValue &m); 00525 00526 00527 public: 00528 00529 mcVALUE_DEFINE_GETSET(mcIntegerValue, mpz); 00530 mcVALUE_DEFINE_ALLOPERATORS(mcIntegerValue, mcMPZ, mpz); 00531 00533 mcIntegerValue abs() const 00534 { mcIntegerValue ret; mpz_abs(ret.MP(), cMP()); return ret; } 00535 00537 mcIntegerValue pow(unsigned long int exp) const 00538 { mcIntegerValue ret; mpz_pow_ui(ret.MP(), cMP(), exp); return ret; } 00539 00540 mcIntegerValue GetMax(const mcIntegerValue &n) const 00541 { if (*this > n) return *this; else return n; } 00542 00543 mcIntegerValue GetMin(const mcIntegerValue &n) const 00544 { if (*this < n) return *this; else return n; } 00545 00547 wxString GetStr() const; 00548 00550 bool isInteger() const { return TRUE; } 00551 00553 bool isPrimeTo(const mcIntegerValue &n) const { return (GCD(n) == 1); } 00554 00555 static mcIntegerValue GetComb(const mcIntegerValue &n1, const mcIntegerValue &n2) 00556 { mcIntegerValue rop; mpz_bin_ui(rop.MP(), n1.cMP(), n2.GetLong()); return rop; } 00557 00566 mcIntegerValue GCD(const mcIntegerValue &n) const 00567 { mcIntegerValue ret; mpz_gcd(ret.MP(), cMP(), n.cMP()); return ret; } 00568 00575 mcIntegerValue LCM(const mcIntegerValue &n) const 00576 { mcIntegerValue ret; mpz_lcm(ret.MP(), cMP(), n.cMP()); return ret; } 00577 }; 00578 00579 00583 class mcRationalValue : public mcValue 00584 { 00585 mcVALUE_DEFINE_COW(mcMPQ, mpq); 00586 00587 public: 00588 mcVALUE_DEFINE_CONSTRUCTORS(mcRationalValue, mcMPQ); 00589 mcRationalValue(const mcIntegerValue &m); 00590 mcRationalValue(const mcRealValue &m); 00591 mcRationalValue(const mcIntegerValue &num, const mcIntegerValue &den); 00592 00593 00594 mcIntegerValue GetDen() const 00595 { mcIntegerValue ret; mpq_get_den(ret.MP(), cMP()); return ret; } 00596 mcIntegerValue GetNum() const 00597 { mcIntegerValue ret; mpq_get_num(ret.MP(), cMP()); return ret; } 00598 00601 void Canonicalize() 00602 { mpq_canonicalize(MP()); } 00603 00604 public: 00605 00606 mcVALUE_DEFINE_SETGET_FLAGS(); 00607 mcVALUE_DEFINE_MISCELLANEOUS(mcRationalValue, mpq); 00608 //mcVALUE_DEFINE_ALLOPERATORS(mcRationalValue, mcMPQ, mpq) 00609 00610 void SetLong(long n) { mpq_set_si(MP(), n, 1); } 00611 void SetDouble(double n) { mpq_set_d(MP(), n); } 00612 void SetStr(const wxString &str, int base = 10) 00613 { mpq_set_str(MP(), WX2GMP(str), base); } 00614 00615 double GetDouble() const { return mpq_get_d(cMP()); } 00616 long GetLong() const { return (long)GetDouble(); } 00617 00619 wxString GetStr() const; 00620 00622 bool isInteger() const { return GetDen() == 1; } 00623 00625 mcRationalValue abs() const 00626 { mcRationalValue ret; mpq_abs(ret.MP(), cMP()); return ret; } 00627 00634 mcRationalValue GetFractionalPart() const; 00635 00637 int GetFractionalDigitCount(int digits = mcVALUE_DEFAULTPRECISION) const; 00638 00642 mcIntegerValue GetIntegerPart() const; 00643 00647 mcIntegerValue MakeInteger(int digits = mcVALUE_DEFAULTPRECISION) const; 00648 }; 00649 00650 00653 class mcRealValue : public mcValue 00654 { 00655 mcVALUE_DEFINE_COW(mcMPF, mpf); 00656 00657 protected: 00658 00660 wxString GetBaseStr(int *p, int digits, int *n) const; 00661 00662 public: // static 00663 00664 static mcRealValue *pOne; 00665 static mcRealValue *pZero; 00666 static mcRealValue *pNAN; 00667 static mcRealValue *pPosInf; 00668 static mcRealValue *pNegInf; 00669 00670 public: 00671 mcVALUE_DEFINE_CONSTRUCTORS(mcRealValue, mcMPF); 00672 mcRealValue(double f) { InternalInit(); SetDouble(f); } 00673 mcRealValue(const mcRationalValue &m) { InternalInit(m.GetFlags()); mpf_set_q(MP(), m.cMP()); } 00674 mcRealValue(const mcIntegerValue &m) { InternalInit(m.GetFlags()); mpf_set_z(MP(), m.cMP()); } 00675 00676 00677 public: // math.h-like functions 00678 00679 mcRealValue pow(unsigned long n) const 00680 { mcRealValue ret; mpf_pow_ui(ret.MP(), cMP(), n); return ret; } 00681 mcRealValue pow(int n) const 00682 { mcRealValue ret; mpf_pow_ui(ret.MP(), cMP(), n); return ret; } 00683 mcRealValue pow(double n) const 00684 { mcRealValue ret; ret.SetDouble(::pow(GetDouble(), n)); return ret; } 00685 mcRealValue pow(const mcRealValue &n) const 00686 { return this->pow(n.GetDouble()); } 00687 mcRealValue root(const mcRealValue &n) 00688 { mcRealValue exp=1.0 / n; return this->pow(exp); } 00689 00690 mcRealValue abs() const { mcRealValue ret; mpf_abs(ret.MP(), cMP()); return ret; } 00691 mcRealValue floor() const { mcRealValue ret; mpf_floor(ret.MP(), cMP()); return ret; } 00692 mcRealValue ceil() const { mcRealValue ret; mpf_ceil(ret.MP(), cMP()); return ret; } 00693 mcRealValue trunc() const { mcRealValue ret; mpf_trunc(ret.MP(), cMP()); return ret; } 00694 00697 bool isInteger() const { return mpf_integer_p(cMP()) != 0; } 00698 00700 mcRealValue GetReciprocal() const { return 1.0 / (*this); } 00701 00702 public: // operators 00703 00704 mcVALUE_DEFINE_ALLOPERATORS(mcRealValue, mcMPF, mpf); 00705 mcVALUE_DEFINE_DOUBLEOPERATORS(mcRealValue, mcMPF, mpf); 00706 mcVALUE_DEFINE_GETSET(mcRealValue, mpf); 00707 mcVALUE_DEFINE_FLAGSCOMPARISON_OPERATORS(mcIntegerValue, mpf_cmp_si, m.GetLong()); 00708 00710 wxString GetStr() const { return GetStr(mcVALUE_DEFAULTPRECISION); } 00711 wxString GetStr(int digits) const; 00712 00723 virtual wxString GetExtStr(int digits = mcVALUE_DEFAULTPRECISION) const; 00724 00728 virtual wxString GetSmartStr(int threshold = mcVALUE_SMARTSTR_THRESHOLD, 00729 int digits = mcVALUE_DEFAULTPRECISION) const; 00730 00731 00732 double GetDouble() const { return mpf_get_d(cMP()); } 00733 void SetDouble(double n) { mpf_set_d(MP(), n); } 00734 00735 mcRealValue &operator=(double d) { SetDouble(d); return *this;} \ 00736 operator double() const { return GetDouble(); } 00737 00738 public: // digit-manipulation functions 00739 00740 // ------------------- 00741 // Digit getters 00742 // ------------------- 00743 00744 int GetNumOfDigits(int digits = mcVALUE_DEFAULTPRECISION) const; 00745 mcRealValue GetFromDigitRange(int begin, int end = -1, int digits = mcVALUE_DEFAULTPRECISION) const; 00746 00747 00748 // -------------------- 00749 // Digit manipulation 00750 // -------------------- 00751 00752 mcRealValue DeleteDigit(int pos, int digits = mcVALUE_DEFAULTPRECISION) const; 00753 mcRealValue InsertDigit(wxChar digit, int pos, int digits = mcVALUE_DEFAULTPRECISION) const; 00754 mcRealValue AppendDigit(wxChar digit, int digits = mcVALUE_DEFAULTPRECISION) const 00755 { return InsertDigit(digit, -1, digits); } 00756 }; 00757 00758 00760 class mcComplexValue : public mcValue 00761 { 00762 00763 00764 }; 00765 00766 00767 00768 00769 00770 /* 00771 class mcNaturalValue : public mcValue 00772 { 00773 };*/ 00774 00775 /* 00776 inline mcValue pow(const mcValue &x,const mcValue &y) {return x.pow(y.GetLong());} 00777 inline mcValue gcd(const mcValue &u,const mcValue &v) {return u.GCD(v);} 00778 inline mcValue lcm(const mcValue &u,const mcValue &v) {return u.LCM(v);} 00779 */ 00780 00781 #endif // VALUE_H
[ Top ] |