00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00030
00031
00032
00033
00034 #ifdef __GNUG__
00035 #pragma implementation "Value.h"
00036 #endif
00037
00038
00039 #include "mc/mcprec.h"
00040 #ifdef __BORLANDC__
00041 #pragma hdrstop
00042 #endif
00043
00044 #ifndef mcPRECOMP
00045 #include <wx/string.h>
00046
00047 #include "mc/MathUtils.h"
00048 #include "mc/Value.h"
00049 #endif
00050
00051
00052
00053 int mcValue::m_nMaxValueSharing = -1;
00054
00055 mcIntegerValue *mcIntegerValue::pOne = NULL;
00056 mcIntegerValue *mcIntegerValue::pZero = NULL;
00057 mcIntegerValue *mcIntegerValue::pNAN = NULL;
00058 mcIntegerValue *mcIntegerValue::pPosInf = NULL;
00059 mcIntegerValue *mcIntegerValue::pNegInf = NULL;
00060
00061 mcRealValue *mcRealValue::pOne = NULL;
00062 mcRealValue *mcRealValue::pZero = NULL;
00063 mcRealValue *mcRealValue::pNAN = NULL;
00064 mcRealValue *mcRealValue::pPosInf = NULL;
00065 mcRealValue *mcRealValue::pNegInf = NULL;
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 void *mcGMPAlloc(size_t n) { return new char[n]; }
00077 void mcGMPFree(void *mem, size_t) { delete [] ((char *)mem); }
00078
00079 void *mcGMPRealloc(void *mem, size_t oldsize, size_t newsize)
00080 {
00081 void *newp = mcGMPAlloc(newsize);
00082
00083
00084 memcpy(newp, mem, mcMIN(oldsize, newsize));
00085 mcGMPFree(mem, oldsize);
00086
00087 return newp;
00088 }
00089
00090
00091
00092
00093
00094
00095
00096
00097 void mcValue::Init()
00098 {
00099
00100 mp_set_memory_functions(mcGMPAlloc, mcGMPRealloc, mcGMPFree);
00101
00102
00103 mcIntegerValue::pNAN = new mcIntegerValue();
00104 mcIntegerValue::pNAN->math_AddFlag(mcVALUE_NAN_FLAG);
00105 mcIntegerValue::pPosInf = new mcIntegerValue();
00106 mcIntegerValue::pPosInf->math_AddFlag(mcVALUE_POSINF_FLAG);
00107 mcIntegerValue::pNegInf = new mcIntegerValue();
00108 mcIntegerValue::pNegInf->math_AddFlag(mcVALUE_NEGINF_FLAG);
00109
00110 mcIntegerValue::pZero = new mcIntegerValue(0);
00111 mcIntegerValue::pOne = new mcIntegerValue(1);
00112
00113
00114 mcRealValue::pNAN = new mcRealValue(*mcIntegerValue::pNAN);
00115 mcRealValue::pPosInf = new mcRealValue(*mcIntegerValue::pPosInf);
00116 mcRealValue::pNegInf = new mcRealValue(*mcIntegerValue::pNegInf);
00117 mcRealValue::pZero = new mcRealValue(0.0);
00118 mcRealValue::pOne = new mcRealValue(1.0);
00119 }
00120
00121 void mcValue::Cleanup()
00122 {
00123
00124 delete mcIntegerValue::pZero;
00125 delete mcIntegerValue::pOne;
00126 delete mcIntegerValue::pNAN;
00127 delete mcIntegerValue::pPosInf;
00128 delete mcIntegerValue::pNegInf;
00129
00130 delete mcRealValue::pZero;
00131 delete mcRealValue::pOne;
00132 delete mcRealValue::pNAN;
00133 delete mcRealValue::pPosInf;
00134 delete mcRealValue::pNegInf;
00135 }
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 mcIntegerValue::mcIntegerValue(const mcRationalValue &m)
00146 { InternalInit(m.GetFlags()); mpz_set_q(MP(), m.cMP()); }
00147
00148 mcIntegerValue::mcIntegerValue(const mcRealValue &m)
00149 { InternalInit(m.GetFlags()); mpz_set_f(MP(), m.cMP()); }
00150
00151 wxString mcIntegerValue::GetStr() const
00152 {
00153
00154 char *buf = new char[mpz_sizeinbase(cMP(), 10)+5];
00155 mpz_get_str(buf, 10, cMP());
00156 wxString str(GMP2WX(buf));
00157 delete [] buf;
00158
00159
00160 if (str.IsEmpty()) str = wxT("0");
00161
00162 return str;
00163 }
00164
00165
00166
00167
00168
00169
00170
00171
00172 mcRationalValue::mcRationalValue(const mcIntegerValue &m)
00173 { InternalInit(m.GetFlags()); mpq_set_z(MP(), m.cMP()); }
00174
00175 mcRationalValue::mcRationalValue(const mcRealValue &m)
00176 { InternalInit(m.GetFlags()); mpq_set_f(MP(), m.cMP()); }
00177
00178 mcRationalValue::mcRationalValue(const mcIntegerValue &num, const mcIntegerValue &den)
00179 { InternalInit(); mpq_set_si(MP(), num.GetLong(), den.GetLong()); }
00180
00181 wxString mcRationalValue::GetStr() const
00182 {
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 mcRealValue r(*this);
00193 return r.GetStr();
00194
00195
00196
00197 }
00198
00199 int mcRationalValue::GetFractionalDigitCount(int max) const
00200 {
00201 mcRealValue n = *this;
00202 int count = 0;
00203
00204
00205 while (!n.isInteger()) {
00206
00207
00208 if (count == max)
00209 break;
00210
00211 n *= 10.0;
00212 count++;
00213 }
00214
00215
00216 if (!n.isInteger())
00217 return -1;
00218
00219 return count;
00220 }
00221
00222 mcIntegerValue mcRationalValue::MakeInteger(int max) const
00223 {
00224 int count = GetFractionalDigitCount(max);
00225 mcRealValue n(*this);
00226
00227 if (count > 0) {
00228
00229
00230
00231
00232 mcRealValue res = n * mcRealValue(10).pow(count);
00233 mcASSERT(res.isInteger(), wxT("Something wrong in the algorithm"));
00234
00235 return mcIntegerValue(res);
00236
00237 } else if (count == 0) {
00238
00239
00240 mcASSERT(isInteger(), wxT("Fractional digit count should not be zero then !!!"));
00241 return *this;
00242 }
00243
00244
00245
00246
00247 mcRealValue res = n * mcRealValue(10).pow(max);
00248 return mcIntegerValue(res.floor());
00249 }
00250
00251
00252
00253
00254
00255
00256
00257
00258 wxString mcRealValue::GetBaseStr(int *p, int digits, int *n) const
00259 {
00260
00261 mp_exp_t exp;
00262 char *buf = new char[digits+5];
00263 mpf_get_str(buf, &exp, 10, digits, cMP());
00264 wxString str(GMP2WX(buf));
00265 delete [] buf;
00266
00267
00268 if (str.IsEmpty()) { str = wxT("0"); exp=1; }
00269 if (p) *p = (int)exp;
00270 if (n) *n = exp - str.Len() + (str.GetChar(0) == wxT('-') ? 1 : 0);
00271
00272 return str;
00273 }
00274
00275 wxString mcRealValue::GetStr(int digits) const
00276 {
00277 int exp, n;
00278 wxString str = GetBaseStr(&exp, digits, &n);
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294 if (n > 0) str += wxString::Format(wxT("E%d"), exp-1);
00295
00296 return str;
00297 }
00298
00299 wxString mcRealValue::GetSmartStr(int threshold, int digits) const
00300 {
00301 int exp, n;
00302 wxString str = GetBaseStr(&exp, digits, &n);
00303
00304
00305 if (n < 0) {
00306
00307 wxString left = str.Left(exp);
00308 if (left.IsEmpty()) left = wxT("0");
00309
00310 str = left + wxT(".") + str.Right(-n);
00311
00312 } else if (n == 0) {
00313
00314
00315 return str;
00316
00317 } else {
00318
00319 if (n < threshold)
00320 str += wxString(wxT('0'), n);
00321 else
00322 str += wxString::Format(wxT("E%d"), exp-1);
00323 }
00324
00325 return str;
00326 }
00327
00328 wxString mcRealValue::GetExtStr(int digits) const
00329 {
00330 int exp, n;
00331 wxString str = GetBaseStr(&exp, digits, &n);
00332
00333
00334 if (n > 0) str += wxString(wxT('0'), n);
00335
00336 return str;
00337 }
00338
00339 mcRealValue mcRealValue::GetFromDigitRange(int begin, int end, int digits) const
00340 {
00341 wxString str = GetSmartStr(digits);
00342
00343
00344 if (end == -1) end = str.Len();
00345
00346
00347 str = str.Mid(begin, end-begin);
00348
00349 return mcRealValue(str);
00350 }
00351
00352 int mcRealValue::GetNumOfDigits(int digits) const
00353 {
00354
00355 wxString tmp = GetSmartStr(digits);
00356 return tmp.Len();
00357 }
00358
00359 mcRealValue mcRealValue::InsertDigit(wxChar digittoadd, int pos, int digits) const
00360 {
00361
00362 wxString str = GetSmartStr(digits);
00363
00364
00365
00366
00367
00368
00369 if (pos == -1) pos = str.Len();
00370 str = str.Left(pos) + digittoadd + str.Right(str.Len()-pos);
00371
00372
00373 return mcRealValue(str);
00374 }
00375
00376 mcRealValue mcRealValue::DeleteDigit(int n, int digits) const
00377 {
00378 wxString str = GetSmartStr(digits);
00379 mcASSERT(n > 0, wxT("The digit to delete must not be zero-based"));
00380
00381
00382 str.Remove(n-1, 1);
00383
00384
00385 return mcRealValue(str);
00386 }
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399