• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kcalc/knumber
 

kcalc/knumber

  • kcalc
  • knumber
knumber.cpp
1 /* This file is part of the KDE libraries
2  Copyright (c) 2005 Klaus Niederkrueger <kniederk@math.uni-koeln.de>
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public
6  License as published by the Free Software Foundation; either
7  version 2 of the License, or (at your option) any later version.
8 
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Library General Public License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to
16  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  Boston, MA 02110-1301, USA.
18 */
19 
20 #include <math.h>
21 
22 #include <config.h>
23 
24 #include <tqregexp.h>
25 #include <tqstring.h>
26 
27 #include "knumber.h"
28 
29 KNumber const KNumber::Zero(0);
30 KNumber const KNumber::One(1);
31 KNumber const KNumber::MinusOne(-1);
32 KNumber const KNumber::Pi("3.141592653589793238462643383279502884197169"
33  "39937510582097494459230781640628620899862803"
34  "4825342117068");
35 KNumber const KNumber::Euler("2.718281828459045235360287471352662497757"
36  "24709369995957496696762772407663035354759"
37  "4571382178525166427");
38 KNumber const KNumber::NotDefined("nan");
39 
40 bool KNumber::_float_output = false;
41 bool KNumber::_fraction_input = false;
42 bool KNumber::_splitoffinteger_output = false;
43 
44 KNumber::KNumber(signed int num)
45 {
46  _num = new _knuminteger(num);
47 }
48 
49 KNumber::KNumber(unsigned int num)
50 {
51  _num = new _knuminteger(num);
52 }
53 
54 KNumber::KNumber(signed long int num)
55 {
56  _num = new _knuminteger(num);
57 }
58 
59 KNumber::KNumber(unsigned long int num)
60 {
61  _num = new _knuminteger(num);
62 }
63 
64 KNumber::KNumber(unsigned long long int num)
65 {
66  _num = new _knuminteger(num);
67 }
68 
69 KNumber::KNumber(double num)
70 {
71  if ( isinf(num) ) _num = new _knumerror( _knumber::Infinity );
72  else if ( isnan(num) ) _num = new _knumerror( _knumber::UndefinedNumber );
73  else _num = new _knumfloat(num);
74 
75 }
76 
77 KNumber::KNumber(KNumber const & num)
78 {
79  switch(num.type()) {
80  case SpecialType:
81  _num = new _knumerror(*(num._num));
82  return;
83  case IntegerType:
84  _num = new _knuminteger(*(num._num));
85  return;
86  case FractionType:
87  _num = new _knumfraction(*(num._num));
88  return;
89  case FloatType:
90  _num = new _knumfloat(*(num._num));
91  return;
92  };
93 }
94 
95 
96 KNumber::KNumber(TQString const & num)
97 {
98  if (TQRegExp("^(inf|-inf|nan)$").exactMatch(num))
99  _num = new _knumerror(num);
100  else if (TQRegExp("^[+-]?\\d+$").exactMatch(num))
101  _num = new _knuminteger(num);
102  else if (TQRegExp("^[+-]?\\d+/\\d+$").exactMatch(num)) {
103  _num = new _knumfraction(num);
104  simplifyRational();
105  }
106  else if (TQRegExp("^[+-]?\\d+(\\.\\d*)?(e[+-]?\\d+)?$").exactMatch(num))
107  if (_fraction_input == true) {
108  _num = new _knumfraction(num);
109  simplifyRational();
110  } else
111  _num = new _knumfloat(num);
112  else
113  _num = new _knumerror("nan");
114 }
115 
116 KNumber::NumType KNumber::type(void) const
117 {
118  if(dynamic_cast<_knumerror *>(_num))
119  return SpecialType;
120  if(dynamic_cast<_knuminteger *>(_num))
121  return IntegerType;
122  if(dynamic_cast<_knumfraction *>(_num))
123  return FractionType;
124  if(dynamic_cast<_knumfloat *>(_num))
125  return FloatType;
126 
127  return SpecialType;
128 }
129 
130 // This method converts a fraction to an integer, whenever possible,
131 // i.e. 5/1 --> 5
132 // This method should be called, whenever such a inproper fraction can occur,
133 // e.g. when adding 4/3 + 2/3....
134 void KNumber::simplifyRational(void)
135 {
136  if (type() != FractionType)
137  return;
138 
139  _knumfraction *tmp_num = dynamic_cast<_knumfraction *>(_num);
140 
141  if (tmp_num->isInteger()) {
142  _knumber *tmp_num2 = tmp_num->intPart();
143  delete tmp_num;
144  _num = tmp_num2;
145  }
146 
147 }
148 
149 
150 KNumber const & KNumber::operator=(KNumber const & num)
151 {
152  if (this == & num)
153  return *this;
154 
155  delete _num;
156 
157  switch(num.type()) {
158  case SpecialType:
159  _num = new _knumerror();
160  break;
161  case IntegerType:
162  _num = new _knuminteger();
163  break;
164  case FractionType:
165  _num = new _knumfraction();
166  break;
167  case FloatType:
168  _num = new _knumfloat();
169  break;
170  };
171 
172  _num->copy(*(num._num));
173 
174  return *this;
175 }
176 
177 KNumber & KNumber::operator +=(KNumber const &arg)
178 {
179  KNumber tmp_num = *this + arg;
180 
181  delete _num;
182 
183  switch(tmp_num.type()) {
184  case SpecialType:
185  _num = new _knumerror();
186  break;
187  case IntegerType:
188  _num = new _knuminteger();
189  break;
190  case FractionType:
191  _num = new _knumfraction();
192  break;
193  case FloatType:
194  _num = new _knumfloat();
195  break;
196  };
197 
198  _num->copy(*(tmp_num._num));
199 
200  return *this;
201 }
202 
203 KNumber & KNumber::operator -=(KNumber const &arg)
204 {
205  KNumber tmp_num = *this - arg;
206 
207  delete _num;
208 
209  switch(tmp_num.type()) {
210  case SpecialType:
211  _num = new _knumerror();
212  break;
213  case IntegerType:
214  _num = new _knuminteger();
215  break;
216  case FractionType:
217  _num = new _knumfraction();
218  break;
219  case FloatType:
220  _num = new _knumfloat();
221  break;
222  };
223 
224  _num->copy(*(tmp_num._num));
225 
226  return *this;
227 }
228 
229 // increase the digit at 'position' by one
230 static void _inc_by_one(TQString &str, int position)
231 {
232  for (int i = position; i >= 0; i--)
233  {
234  char last_char = str[i].latin1();
235  switch(last_char)
236  {
237  case '0':
238  str[i] = '1';
239  break;
240  case '1':
241  str[i] = '2';
242  break;
243  case '2':
244  str[i] = '3';
245  break;
246  case '3':
247  str[i] = '4';
248  break;
249  case '4':
250  str[i] = '5';
251  break;
252  case '5':
253  str[i] = '6';
254  break;
255  case '6':
256  str[i] = '7';
257  break;
258  case '7':
259  str[i] = '8';
260  break;
261  case '8':
262  str[i] = '9';
263  break;
264  case '9':
265  str[i] = '0';
266  if (i == 0) str.prepend('1');
267  continue;
268  case '.':
269  continue;
270  }
271  break;
272  }
273 }
274 
275 // Cut off if more digits in fractional part than 'precision'
276 static void _round(TQString &str, int precision)
277 {
278  int decimalSymbolPos = str.find('.');
279 
280  if (decimalSymbolPos == -1)
281  if (precision == 0) return;
282  else if (precision > 0) // add dot if missing (and needed)
283  {
284  str.append('.');
285  decimalSymbolPos = str.length() - 1;
286  }
287 
288  // fill up with more than enough zeroes (in case fractional part too short)
289  str.append(TQString().fill('0', precision));
290 
291  // Now decide whether to round up or down
292  char last_char = str[decimalSymbolPos + precision + 1].latin1();
293  switch (last_char)
294  {
295  case '0':
296  case '1':
297  case '2':
298  case '3':
299  case '4':
300  // nothing to do, rounding down
301  break;
302  case '5':
303  case '6':
304  case '7':
305  case '8':
306  case '9':
307  // rounding up
308  _inc_by_one(str, decimalSymbolPos + precision);
309  break;
310  default:
311  break;
312  }
313 
314  decimalSymbolPos = str.find('.');
315  str.truncate(decimalSymbolPos + precision + 1);
316 
317  // if precision == 0 delete also '.'
318  if (precision == 0) str = str.section('.', 0, 0);
319 }
320 
321 static TQString roundNumber(const TQString &numStr, int precision)
322 {
323  TQString tmpString = numStr;
324  if (precision < 0 ||
325  ! TQRegExp("^[+-]?\\d+(\\.\\d+)*(e[+-]?\\d+)?$").exactMatch(tmpString))
326  return numStr;
327 
328 
329  // Skip the sign (for now)
330  bool neg = (tmpString[0] == '-');
331  if (neg || tmpString[0] == '+') tmpString.remove(0, 1);
332 
333 
334  // Split off exponential part (including 'e'-symbol)
335  TQString mantString = tmpString.section('e', 0, 0,
336  TQString::SectionCaseInsensitiveSeps);
337  TQString expString = tmpString.section('e', 1, 1,
338  TQString::SectionCaseInsensitiveSeps |
339  TQString::SectionIncludeLeadingSep);
340  if (expString.length() == 1) expString = TQString();
341 
342 
343  _round(mantString, precision);
344 
345  if(neg) mantString.prepend('-');
346 
347  return mantString + expString;
348 }
349 
350 
351 TQString const KNumber::toTQString(int width, int prec) const
352 {
353  TQString tmp_str;
354 
355  if (*this == Zero) // important to avoid infinite loops below
356  return "0";
357  switch (type()) {
358  case IntegerType:
359  if (width > 0) { //result needs to be cut-off
360  bool tmp_bool = _fraction_input; // stupid work-around
361  _fraction_input = false;
362  tmp_str = (KNumber("1.0")*(*this)).toTQString(width, -1);
363  _fraction_input = tmp_bool;
364  } else
365  tmp_str = TQString(_num->ascii());
366  break;
367  case FractionType:
368  if (_float_output) {
369  bool tmp_bool = _fraction_input; // stupid work-around
370  _fraction_input = false;
371  tmp_str = (KNumber("1.0")*(*this)).toTQString(width, -1);
372  _fraction_input = tmp_bool;
373  } else { // _float_output == false
374  if(_splitoffinteger_output) {
375  // split off integer part
376  KNumber int_part = this->integerPart();
377  if (int_part == Zero)
378  tmp_str = TQString(_num->ascii());
379  else if (int_part < Zero)
380  tmp_str = int_part.toTQString() + " " + (int_part - *this)._num->ascii();
381  else
382  tmp_str = int_part.toTQString() + " " + (*this - int_part)._num->ascii();
383  } else
384  tmp_str = TQString(_num->ascii());
385 
386  if (width > 0 && tmp_str.length() > width) {
387  //result needs to be cut-off
388  bool tmp_bool = _fraction_input; // stupid work-around
389  _fraction_input = false;
390  tmp_str = (KNumber("1.0")*(*this)).toTQString(width, -1);
391  _fraction_input = tmp_bool;
392  }
393  }
394 
395  break;
396  case FloatType:
397  if (width > 0)
398  tmp_str = TQString(_num->ascii(width));
399  else
400  // rough estimate for maximal decimal precision (10^3 = 2^10)
401  tmp_str = TQString(_num->ascii(3*mpf_get_default_prec()/10));
402  break;
403  default:
404  return TQString(_num->ascii());
405  }
406 
407  if (prec >= 0)
408  return roundNumber(tmp_str, prec);
409  else
410  return tmp_str;
411 }
412 
413 void KNumber::setDefaultFloatOutput(bool flag)
414 {
415  _float_output = flag;
416 }
417 
418 void KNumber::setDefaultFractionalInput(bool flag)
419 {
420  _fraction_input = flag;
421 }
422 
423 void KNumber::setSplitoffIntegerForFractionOutput(bool flag)
424 {
425  _splitoffinteger_output = flag;
426 }
427 
428 void KNumber::setDefaultFloatPrecision(unsigned int prec)
429 {
430  // Need to transform decimal digits into binary digits
431  unsigned long int bin_prec = static_cast<unsigned long int>
432  (double(prec) * M_LN10 / M_LN2 + 1);
433 
434  mpf_set_default_prec(bin_prec);
435 }
436 
437 KNumber const KNumber::abs(void) const
438 {
439  KNumber tmp_num;
440  delete tmp_num._num;
441 
442  tmp_num._num = _num->abs();
443 
444  return tmp_num;
445 }
446 
447 KNumber const KNumber::cbrt(void) const
448 {
449  KNumber tmp_num;
450  delete tmp_num._num;
451 
452  tmp_num._num = _num->cbrt();
453 
454  return tmp_num;
455 }
456 
457 KNumber const KNumber::sqrt(void) const
458 {
459  KNumber tmp_num;
460  delete tmp_num._num;
461 
462  tmp_num._num = _num->sqrt();
463 
464  return tmp_num;
465 }
466 
467 KNumber const KNumber::integerPart(void) const
468 {
469  KNumber tmp_num;
470  delete tmp_num._num;
471  tmp_num._num = _num->intPart();
472 
473  return tmp_num;
474 }
475 
476 KNumber const KNumber::power(KNumber const &exp) const
477 {
478  if (*this == Zero) {
479  if(exp == Zero)
480  return KNumber("nan"); // 0^0 not defined
481  else if (exp < Zero)
482  return KNumber("inf");
483  else
484  return KNumber(0);
485  }
486 
487  if (exp == Zero) {
488  if (*this != Zero)
489  return One;
490  else
491  return KNumber("nan");
492  }
493  else if (exp < Zero) {
494  KNumber tmp_num;
495  KNumber tmp_num2 = -exp;
496  delete tmp_num._num;
497  tmp_num._num = _num->power(*(tmp_num2._num));
498 
499  return One/tmp_num;
500  }
501  else {
502  KNumber tmp_num;
503  delete tmp_num._num;
504  tmp_num._num = _num->power(*(exp._num));
505 
506  return tmp_num;
507  }
508 
509 }
510 
511 KNumber const KNumber::operator-(void) const
512 {
513  KNumber tmp_num;
514  delete tmp_num._num;
515 
516  tmp_num._num = _num->change_sign();
517 
518  return tmp_num;
519 }
520 
521 KNumber const KNumber::operator+(KNumber const & arg2) const
522 {
523  KNumber tmp_num;
524  delete tmp_num._num;
525 
526  tmp_num._num = _num->add(*arg2._num);
527 
528  tmp_num.simplifyRational();
529 
530  return tmp_num;
531 }
532 
533 KNumber const KNumber::operator-(KNumber const & arg2) const
534 {
535  return *this + (-arg2);
536 }
537 
538 KNumber const KNumber::operator*(KNumber const & arg2) const
539 {
540  KNumber tmp_num;
541  delete tmp_num._num;
542 
543  tmp_num._num = _num->multiply(*arg2._num);
544 
545  tmp_num.simplifyRational();
546 
547  return tmp_num;
548 }
549 
550 KNumber const KNumber::operator/(KNumber const & arg2) const
551 {
552  KNumber tmp_num;
553  delete tmp_num._num;
554 
555  tmp_num._num = _num->divide(*arg2._num);
556 
557  tmp_num.simplifyRational();
558 
559  return tmp_num;
560 }
561 
562 
563 KNumber const KNumber::operator%(KNumber const & arg2) const
564 {
565  if (type() != IntegerType || arg2.type() != IntegerType)
566  return Zero;
567 
568  KNumber tmp_num;
569  delete tmp_num._num;
570 
571  _knuminteger const *tmp_arg1 = dynamic_cast<_knuminteger const *>(_num);
572  _knuminteger const *tmp_arg2 = dynamic_cast<_knuminteger const *>(arg2._num);
573 
574  tmp_num._num = tmp_arg1->mod(*tmp_arg2);
575 
576  return tmp_num;
577 }
578 
579 KNumber const KNumber::operator&(KNumber const & arg2) const
580 {
581  if (type() != IntegerType || arg2.type() != IntegerType)
582  return Zero;
583 
584  KNumber tmp_num;
585  delete tmp_num._num;
586 
587  _knuminteger const *tmp_arg1 = dynamic_cast<_knuminteger const *>(_num);
588  _knuminteger const *tmp_arg2 = dynamic_cast<_knuminteger const *>(arg2._num);
589 
590  tmp_num._num = tmp_arg1->intAnd(*tmp_arg2);
591 
592  return tmp_num;
593 
594 }
595 
596 KNumber const KNumber::operator|(KNumber const & arg2) const
597 {
598  if (type() != IntegerType || arg2.type() != IntegerType)
599  return Zero;
600 
601  KNumber tmp_num;
602  delete tmp_num._num;
603 
604  _knuminteger const *tmp_arg1 = dynamic_cast<_knuminteger const *>(_num);
605  _knuminteger const *tmp_arg2 = dynamic_cast<_knuminteger const *>(arg2._num);
606 
607  tmp_num._num = tmp_arg1->intOr(*tmp_arg2);
608 
609  return tmp_num;
610 }
611 
612 
613 KNumber const KNumber::operator<<(KNumber const & arg2) const
614 {
615  if (type() != IntegerType || arg2.type() != IntegerType)
616  return KNumber("nan");
617 
618  _knuminteger const *tmp_arg1 = dynamic_cast<_knuminteger const *>(_num);
619  _knuminteger const *tmp_arg2 = dynamic_cast<_knuminteger const *>(arg2._num);
620 
621  KNumber tmp_num;
622  delete tmp_num._num;
623  tmp_num._num = tmp_arg1->shift(*tmp_arg2);
624 
625  return tmp_num;
626 }
627 
628 KNumber const KNumber::operator>>(KNumber const & arg2) const
629 {
630  if (type() != IntegerType || arg2.type() != IntegerType)
631  return KNumber("nan");
632 
633  KNumber tmp_num = -arg2;
634 
635  _knuminteger const *tmp_arg1 = dynamic_cast<_knuminteger const *>(_num);
636  _knuminteger const *tmp_arg2 = dynamic_cast<_knuminteger const *>(tmp_num._num);
637 
638  KNumber tmp_num2;
639  delete tmp_num2._num;
640  tmp_num2._num = tmp_arg1->shift(*tmp_arg2);
641 
642  return tmp_num2;
643 }
644 
645 
646 
647 KNumber::operator bool(void) const
648 {
649  if (*this == Zero)
650  return false;
651  return true;
652 }
653 
654 KNumber::operator signed long int(void) const
655 {
656  return static_cast<signed long int>(*_num);
657 }
658 
659 KNumber::operator unsigned long int(void) const
660 {
661  return static_cast<unsigned long int>(*_num);
662 }
663 
664 KNumber::operator unsigned long long int(void) const
665 {
666 #if SIZEOF_UNSIGNED_LONG == 8
667  return static_cast<unsigned long int>(*this);
668 #elif SIZEOF_UNSIGNED_LONG == 4
669  KNumber tmp_num1 = this->abs().integerPart();
670  unsigned long long int tmp_num2 = static_cast<unsigned long int>(tmp_num1) +
671  (static_cast<unsigned long long int>(
672  static_cast<unsigned long int>(tmp_num1 >> KNumber("32"))) << 32) ;
673 
674 #warning the cast operator from KNumber to unsigned long long int is probably buggy, when a sign is involved
675  if (*this > KNumber(0))
676  return tmp_num2;
677  else
678  return static_cast<unsigned long long int> (- static_cast<signed long long int>(tmp_num2));
679 #else
680 #error "SIZEOF_UNSIGNED_LONG is a unhandled case"
681 #endif
682 }
683 
684 KNumber::operator double(void) const
685 {
686  return static_cast<double>(*_num);
687 }
688 
689 int const KNumber::compare(KNumber const & arg2) const
690 {
691  return _num->compare(*arg2._num);
692 }
KNumber::type
NumType type(void) const
Returns the type of the number, as explained in KNumber::NumType.
Definition: knumber.cpp:116
KNumber::setDefaultFractionalInput
static void setDefaultFractionalInput(bool flag)
Set whether a number constructed from a TQString should be initialized as a fraction or as a float...
Definition: knumber.cpp:418
KNumber::sqrt
KNumber const sqrt(void) const
Compute the square root.
Definition: knumber.cpp:457
KNumber::setDefaultFloatOutput
static void setDefaultFloatOutput(bool flag)
Set whether the output of numbers (with KNumber::toTQString) should happen as floating point numbers ...
Definition: knumber.cpp:413
KNumber::toTQString
TQString const toTQString(int width=-1, int prec=-1) const
Return a TQString representing the KNumber.
Definition: knumber.cpp:351
KNumber::setSplitoffIntegerForFractionOutput
static void setSplitoffIntegerForFractionOutput(bool flag)
What a terrible method name!! When displaying a fraction, the default mode gives "nomin/denom".
Definition: knumber.cpp:423
KNumber::cbrt
KNumber const cbrt(void) const
Compute the cube root.
Definition: knumber.cpp:447
KNumber::integerPart
KNumber const integerPart(void) const
Truncates a KNumber to its integer type returning a number of type NumType::IntegerType.
Definition: knumber.cpp:467
KNumber::abs
KNumber const abs(void) const
Compute the absolute value, i.e.
Definition: knumber.cpp:437
KNumber
Class that provides arbitrary precision numbers.
Definition: knumber.h:62
KNumber::NumType
NumType
KNumber tries to provide transparent access to the following type of numbers:
Definition: knumber.h:86
KNumber::setDefaultFloatPrecision
static void setDefaultFloatPrecision(unsigned int prec)
Set the default precision to be at least prec (decimal) digits.
Definition: knumber.cpp:428

kcalc/knumber

Skip menu "kcalc/knumber"
  • Main Page
  • Alphabetical List
  • Class List
  • File List
  • Class Members

kcalc/knumber

Skip menu "kcalc/knumber"
  • kcalc
  •   knumber
  • superkaramba
Generated for kcalc/knumber by doxygen 1.8.13
This website is maintained by Timothy Pearson.