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

kcalc/knumber

  • kcalc
  • knumber
knumber_priv.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 #include <config.h>
22 
23 #ifdef HAVE_STDLIB_H
24 #include <stdlib.h>
25 #endif
26 #include <tqregexp.h>
27 #include <tqstring.h>
28 
29 #include "knumber_priv.h"
30 
31 _knumerror::_knumerror(_knumber const & num)
32 {
33  switch(num.type()) {
34  case SpecialType:
35  _error = dynamic_cast<_knumerror const &>(num)._error;
36  break;
37  case IntegerType:
38  case FractionType:
39  case FloatType:
40  // What should I do here?
41  break;
42  }
43 }
44 
45 
46 
47 _knuminteger::_knuminteger(unsigned long long int num)
48 {
49  mpz_init(_mpz);
50 #if SIZEOF_UNSIGNED_LONG == 8
51  mpz_init_set_ui(_mpz, static_cast<unsigned long int>(num));
52 #elif SIZEOF_UNSIGNED_LONG == 4
53  mpz_set_ui(_mpz, static_cast<unsigned long int>(num >> 32));
54  mpz_mul_2exp(_mpz, _mpz, 32);
55  mpz_add_ui(_mpz, _mpz, static_cast<unsigned long int>(num));
56 #else
57 #error "SIZEOF_UNSIGNED_LONG is a unhandled case"
58 #endif
59 }
60 
61 
62 _knuminteger::_knuminteger(_knumber const & num)
63 {
64  mpz_init(_mpz);
65 
66  switch(num.type()) {
67  case IntegerType:
68  mpz_set(_mpz, dynamic_cast<_knuminteger const &>(num)._mpz);
69  break;
70  case FractionType:
71  case FloatType:
72  case SpecialType:
73  // What should I do here?
74  break;
75  }
76 }
77 
78 _knumfraction::_knumfraction(_knumber const & num)
79 {
80  mpq_init(_mpq);
81 
82  switch(num.type()) {
83  case IntegerType:
84  mpq_set_z(_mpq, dynamic_cast<_knuminteger const &>(num)._mpz);
85  break;
86  case FractionType:
87  mpq_set(_mpq, dynamic_cast<_knumfraction const &>(num)._mpq);
88  break;
89  case FloatType:
90  case SpecialType:
91  // What should I do here?
92  break;
93  }
94 }
95 
96 _knumfloat::_knumfloat(_knumber const & num)
97 {
98  mpf_init(_mpf);
99 
100  switch(num.type()) {
101  case IntegerType:
102  mpf_set_z(_mpf, dynamic_cast<_knuminteger const &>(num)._mpz);
103  break;
104  case FractionType:
105  mpf_set_q(_mpf, dynamic_cast<_knumfraction const &>(num)._mpq);
106  break;
107  case FloatType:
108  mpf_set(_mpf, dynamic_cast<_knumfloat const &>(num)._mpf);
109  break;
110  case SpecialType:
111  // What should I do here?
112  break;
113  }
114 }
115 
116 
117 
118 _knumerror::_knumerror(TQString const & num)
119 {
120  if (num == "nan")
121  _error = UndefinedNumber;
122  else if (num == "inf")
123  _error = Infinity;
124  else if (num == "-inf")
125  _error = MinusInfinity;
126 }
127 
128 _knuminteger::_knuminteger(TQString const & num)
129 {
130  mpz_init(_mpz);
131  mpz_set_str(_mpz, num.ascii(), 10);
132 }
133 
134 _knumfraction::_knumfraction(TQString const & num)
135 {
136  mpq_init(_mpq);
137  if (TQRegExp("^[+-]?\\d+(\\.\\d*)?(e[+-]?\\d+)?$").exactMatch(num)) {
138  // my hand-made conversion is terrible
139  // first me convert the mantissa
140  unsigned long int digits_after_dot = ((num.section( '.', 1, 1)).section('e', 0, 0)).length();
141  TQString tmp_num = num.section('e', 0, 0).remove('.');
142  mpq_set_str(_mpq, tmp_num.ascii(), 10);
143  mpz_t tmp_int;
144  mpz_init(tmp_int);
145  mpz_ui_pow_ui (tmp_int, 10, digits_after_dot);
146  mpz_mul(mpq_denref(_mpq), mpq_denref(_mpq), tmp_int);
147  // now we take care of the exponent
148  if (! (tmp_num = num.section('e', 1, 1)).isEmpty()) {
149  long int tmp_exp = tmp_num.toLong();
150  if (tmp_exp > 0) {
151  mpz_ui_pow_ui (tmp_int, 10,
152  static_cast<unsigned long int>(tmp_exp));
153  mpz_mul(mpq_numref(_mpq), mpq_numref(_mpq), tmp_int);
154  } else {
155  mpz_ui_pow_ui (tmp_int, 10,
156  static_cast<unsigned long int>(-tmp_exp));
157  mpz_mul(mpq_denref(_mpq), mpq_denref(_mpq), tmp_int);
158  }
159  }
160  mpz_clear(tmp_int);
161  } else
162  mpq_set_str(_mpq, num.ascii(), 10);
163  mpq_canonicalize(_mpq);
164 }
165 
166 _knumfloat::_knumfloat(TQString const & num)
167 {
168  mpf_init(_mpf);
169  mpf_set_str(_mpf, num.ascii(), 10);
170 }
171 
172 _knuminteger const & _knuminteger::operator = (_knuminteger const & num)
173 {
174  if (this == &num)
175  return *this;
176 
177  mpz_set(_mpz, num._mpz);
178  return *this;
179 }
180 
181 TQString const _knumerror::ascii(int prec) const
182 {
183  static_cast<void>(prec);
184 
185  switch(_error) {
186  case UndefinedNumber:
187  return TQString("nan");
188  case Infinity:
189  return TQString("inf");
190  case MinusInfinity:
191  return TQString("-inf");
192  default:
193  return TQString();
194  }
195 }
196 
197 TQString const _knuminteger::ascii(int prec) const
198 {
199  static_cast<void>(prec);
200  char *tmp_ptr;
201 
202  gmp_asprintf(&tmp_ptr, "%Zd", _mpz);
203  TQString ret_str = tmp_ptr;
204 
205  free(tmp_ptr);
206  return ret_str;
207 }
208 
209 TQString const _knumfraction::ascii(int prec) const
210 {
211  static_cast<void>(prec);
212  char *tmp_ptr = mpq_get_str(0, 10, _mpq);
213  TQString ret_str = tmp_ptr;
214 
215  free(tmp_ptr);
216 
217  return ret_str;
218 }
219 
220 TQString const _knumfloat::ascii(int prec) const
221 {
222  TQString ret_str;
223  char *tmp_ptr;
224  if (prec > 0)
225  gmp_asprintf(&tmp_ptr, ("%." + TQString(TQString().setNum(prec) + "Fg")).ascii(), _mpf);
226  else
227  gmp_asprintf(&tmp_ptr, "%Fg", _mpf);
228 
229  ret_str = tmp_ptr;
230 
231  free(tmp_ptr);
232 
233  return ret_str;
234 }
235 
236 
237 bool _knumfraction::isInteger(void) const
238 {
239  if (mpz_cmp_ui(mpq_denref(_mpq), 1) == 0)
240  return true;
241  else
242  return false;
243 }
244 
245 
246 _knumber * _knumerror::abs(void) const
247 {
248  _knumerror * tmp_num = new _knumerror(*this);
249 
250  if(_error == MinusInfinity) tmp_num->_error = Infinity;
251 
252  return tmp_num;
253 }
254 
255 _knumber * _knuminteger::abs(void) const
256 {
257  _knuminteger * tmp_num = new _knuminteger();
258 
259  mpz_abs(tmp_num->_mpz, _mpz);
260 
261  return tmp_num;
262 }
263 
264 _knumber * _knumfraction::abs(void) const
265 {
266  _knumfraction * tmp_num = new _knumfraction();
267 
268  mpq_abs(tmp_num->_mpq, _mpq);
269 
270  return tmp_num;
271 }
272 
273 _knumber * _knumfloat::abs(void) const
274 {
275  _knumfloat * tmp_num = new _knumfloat();
276 
277  mpf_abs(tmp_num->_mpf, _mpf);
278 
279  return tmp_num;
280 }
281 
282 
283 
284 _knumber * _knumerror::intPart(void) const
285 {
286  return new _knumerror(*this);
287 }
288 
289 _knumber * _knuminteger::intPart(void) const
290 {
291  _knuminteger *tmp_num = new _knuminteger();
292  mpz_set(tmp_num->_mpz, _mpz);
293  return tmp_num;
294 }
295 
296 _knumber * _knumfraction::intPart(void) const
297 {
298  _knuminteger *tmp_num = new _knuminteger();
299 
300  mpz_set_q(tmp_num->_mpz, _mpq);
301 
302  return tmp_num;
303 }
304 
305 _knumber * _knumfloat::intPart(void) const
306 {
307  _knuminteger *tmp_num = new _knuminteger();
308 
309  mpz_set_f(tmp_num->_mpz, _mpf);
310 
311  return tmp_num;
312 }
313 
314 
315 
316 
317 int _knumerror::sign(void) const
318 {
319  switch(_error) {
320  case Infinity:
321  return 1;
322  case MinusInfinity:
323  return -1;
324  default:
325  return 0;
326  }
327 }
328 
329 int _knuminteger::sign(void) const
330 {
331  return mpz_sgn(_mpz);
332 }
333 
334 int _knumfraction::sign(void) const
335 {
336  return mpq_sgn(_mpq);
337 }
338 
339 int _knumfloat::sign(void) const
340 {
341  return mpf_sgn(_mpf);
342 }
343 
344 
345 
346 #warning _cbrt for now this is a stupid work around
347 static void _cbrt(mpf_t &num)
348 {
349  double tmp_num = cbrt(mpf_get_d(num));
350  mpf_init_set_d(num, tmp_num);
351 }
352 
353 
354 _knumber * _knumerror::cbrt(void) const
355 {
356  // infty ^3 = infty; -infty^3 = -infty
357  _knumerror *tmp_num = new _knumerror(*this);
358 
359  return tmp_num;
360 }
361 
362 _knumber * _knuminteger::cbrt(void) const
363 {
364  _knuminteger * tmp_num = new _knuminteger();
365 
366  if(mpz_root(tmp_num->_mpz, _mpz, 3))
367  return tmp_num; // root is perfect
368 
369  delete tmp_num; // root was not perfect, result will be float
370 
371  _knumfloat * tmp_num2 = new _knumfloat();
372  mpf_set_z(tmp_num2->_mpf, _mpz);
373 
374  _cbrt(tmp_num2->_mpf);
375 
376  return tmp_num2;
377 }
378 
379 _knumber * _knumfraction::cbrt(void) const
380 {
381  _knumfraction * tmp_num = new _knumfraction();
382  if (mpz_root(mpq_numref(tmp_num->_mpq), mpq_numref(_mpq), 3)
383  && mpz_root(mpq_denref(tmp_num->_mpq), mpq_denref(_mpq), 3))
384  return tmp_num; // root is perfect
385 
386  delete tmp_num; // root was not perfect, result will be float
387 
388  _knumfloat * tmp_num2 = new _knumfloat();
389  mpf_set_q(tmp_num2->_mpf, _mpq);
390 
391  _cbrt(tmp_num2->_mpf);
392 
393  return tmp_num2;
394 }
395 
396 _knumber * _knumfloat::cbrt(void) const
397 {
398  _knumfloat * tmp_num = new _knumfloat(*this);
399 
400  _cbrt(tmp_num->_mpf);
401 
402  return tmp_num;
403 }
404 
405 
406 
407 
408 _knumber * _knumerror::sqrt(void) const
409 {
410  _knumerror *tmp_num = new _knumerror(*this);
411 
412  if(_error == MinusInfinity) tmp_num->_error = UndefinedNumber;
413 
414  return tmp_num;
415 }
416 
417 _knumber * _knuminteger::sqrt(void) const
418 {
419  if (mpz_sgn(_mpz) < 0) {
420  _knumerror *tmp_num = new _knumerror(UndefinedNumber);
421  return tmp_num;
422  }
423  if (mpz_perfect_square_p(_mpz)) {
424  _knuminteger * tmp_num = new _knuminteger();
425 
426  mpz_sqrt(tmp_num->_mpz, _mpz);
427 
428  return tmp_num;
429  } else {
430  _knumfloat * tmp_num = new _knumfloat();
431  mpf_set_z(tmp_num->_mpf, _mpz);
432  mpf_sqrt(tmp_num->_mpf, tmp_num->_mpf);
433 
434  return tmp_num;
435  }
436 }
437 
438 _knumber * _knumfraction::sqrt(void) const
439 {
440  if (mpq_sgn(_mpq) < 0) {
441  _knumerror *tmp_num = new _knumerror(UndefinedNumber);
442  return tmp_num;
443  }
444  if (mpz_perfect_square_p(mpq_numref(_mpq))
445  && mpz_perfect_square_p(mpq_denref(_mpq))) {
446  _knumfraction * tmp_num = new _knumfraction();
447  mpq_set(tmp_num->_mpq, _mpq);
448  mpz_sqrt(mpq_numref(tmp_num->_mpq), mpq_numref(tmp_num->_mpq));
449  mpz_sqrt(mpq_denref(tmp_num->_mpq), mpq_denref(tmp_num->_mpq));
450 
451  return tmp_num;
452  } else {
453  _knumfloat * tmp_num = new _knumfloat();
454  mpf_set_q(tmp_num->_mpf, _mpq);
455  mpf_sqrt(tmp_num->_mpf, tmp_num->_mpf);
456 
457  return tmp_num;
458  }
459 
460  _knumfraction * tmp_num = new _knumfraction();
461 
462  return tmp_num;
463 }
464 
465 _knumber * _knumfloat::sqrt(void) const
466 {
467  if (mpf_sgn(_mpf) < 0) {
468  _knumerror *tmp_num = new _knumerror(UndefinedNumber);
469  return tmp_num;
470  }
471  _knumfloat * tmp_num = new _knumfloat();
472 
473  mpf_sqrt(tmp_num->_mpf, _mpf);
474 
475  return tmp_num;
476 }
477 
478 
479 
480 _knumber * _knumerror::change_sign(void) const
481 {
482  _knumerror * tmp_num = new _knumerror();
483 
484  if(_error == Infinity) tmp_num->_error = MinusInfinity;
485  if(_error == MinusInfinity) tmp_num->_error = Infinity;
486 
487  return tmp_num;
488 }
489 
490 _knumber * _knuminteger::change_sign(void) const
491 {
492  _knuminteger * tmp_num = new _knuminteger();
493 
494  mpz_neg(tmp_num->_mpz, _mpz);
495 
496  return tmp_num;
497 }
498 
499 _knumber * _knumfraction::change_sign(void) const
500 {
501  _knumfraction * tmp_num = new _knumfraction();
502 
503  mpq_neg(tmp_num->_mpq, _mpq);
504 
505  return tmp_num;
506 }
507 
508 _knumber *_knumfloat::change_sign(void) const
509 {
510  _knumfloat * tmp_num = new _knumfloat();
511 
512  mpf_neg(tmp_num->_mpf, _mpf);
513 
514  return tmp_num;
515 }
516 
517 
518 _knumber * _knumerror::reciprocal(void) const
519 {
520  switch(_error) {
521  case Infinity:
522  case MinusInfinity:
523  return new _knuminteger(0);
524  case UndefinedNumber:
525  default:
526  return new _knumerror(UndefinedNumber);
527  }
528 }
529 
530 _knumber * _knuminteger::reciprocal(void) const
531 {
532  if(mpz_cmp_si(_mpz, 0) == 0) return new _knumerror(Infinity);
533 
534  _knumfraction * tmp_num = new _knumfraction(*this);
535 
536  mpq_inv(tmp_num->_mpq, tmp_num->_mpq);
537 
538  return tmp_num;
539 }
540 
541 _knumber * _knumfraction::reciprocal() const
542 {
543  if(mpq_cmp_si(_mpq, 0, 1) == 0) return new _knumerror(Infinity);
544 
545  _knumfraction * tmp_num = new _knumfraction();
546 
547  mpq_inv(tmp_num->_mpq, _mpq);
548 
549  return tmp_num;
550 }
551 
552 _knumber *_knumfloat::reciprocal(void) const
553 {
554  if(mpf_cmp_si(_mpf, 0) == 0) return new _knumerror(Infinity);
555 
556  _knumfloat * tmp_num = new _knumfloat();
557 
558  mpf_div(tmp_num->_mpf, _knumfloat("1.0")._mpf, _mpf);
559 
560  return tmp_num;
561 }
562 
563 
564 
565 _knumber * _knumerror::add(_knumber const & arg2) const
566 {
567  if (arg2.type() != SpecialType)
568  return new _knumerror(_error);
569 
570  _knumerror const & tmp_arg2 = dynamic_cast<_knumerror const &>(arg2);
571 
572  if (_error == UndefinedNumber
573  || tmp_arg2._error == UndefinedNumber
574  || (_error == Infinity && tmp_arg2._error == MinusInfinity)
575  || (_error == MinusInfinity && tmp_arg2._error == Infinity)
576  )
577  return new _knumerror(UndefinedNumber);
578 
579  return new _knumerror(_error);
580 }
581 
582 _knumber * _knuminteger::add(_knumber const & arg2) const
583 {
584  if (arg2.type() != IntegerType)
585  return arg2.add(*this);
586 
587  _knuminteger * tmp_num = new _knuminteger();
588 
589  mpz_add(tmp_num->_mpz, _mpz,
590  dynamic_cast<_knuminteger const &>(arg2)._mpz);
591 
592  return tmp_num;
593 }
594 
595 _knumber * _knumfraction::add(_knumber const & arg2) const
596 {
597  if (arg2.type() == IntegerType) {
598  // need to cast arg2 to fraction
599  _knumfraction tmp_num(arg2);
600  return tmp_num.add(*this);
601  }
602 
603 
604  if (arg2.type() == FloatType || arg2.type() == SpecialType)
605  return arg2.add(*this);
606 
607  _knumfraction * tmp_num = new _knumfraction();
608 
609  mpq_add(tmp_num->_mpq, _mpq,
610  dynamic_cast<_knumfraction const &>(arg2)._mpq);
611 
612  return tmp_num;
613 }
614 
615 _knumber *_knumfloat::add(_knumber const & arg2) const
616 {
617  if (arg2.type() == SpecialType)
618  return arg2.add(*this);
619 
620  if (arg2.type() != FloatType) {
621  // need to cast arg2 to float
622  _knumfloat tmp_num(arg2);
623  return tmp_num.add(*this);
624  }
625 
626  _knumfloat * tmp_num = new _knumfloat();
627 
628  mpf_add(tmp_num->_mpf, _mpf,
629  dynamic_cast<_knumfloat const &>(arg2)._mpf);
630 
631  return tmp_num;
632 }
633 
634 
635 _knumber * _knumerror::multiply(_knumber const & arg2) const
636 {
637  //improve this
638  switch(arg2.type()) {
639  case SpecialType:
640  {
641  _knumerror const & tmp_arg2 = dynamic_cast<_knumerror const &>(arg2);
642  if (_error == UndefinedNumber || tmp_arg2._error == UndefinedNumber)
643  return new _knumerror(UndefinedNumber);
644  if ( this->sign() * arg2.sign() > 0)
645  return new _knumerror(Infinity);
646  else
647  return new _knumerror(MinusInfinity);
648  }
649  case IntegerType:
650  case FractionType:
651  case FloatType:
652  {
653  int sign_arg2 = arg2.sign();
654  if (_error == UndefinedNumber || sign_arg2 == 0)
655  return new _knumerror(UndefinedNumber);
656  if ( (_error == Infinity && sign_arg2 > 0) ||
657  (_error == MinusInfinity && sign_arg2 < 0) )
658  return new _knumerror(Infinity);
659 
660  return new _knumerror(MinusInfinity);
661  }
662  }
663 
664  return new _knumerror(_error);
665 }
666 
667 
668 _knumber * _knuminteger::multiply(_knumber const & arg2) const
669 {
670  if (arg2.type() != IntegerType)
671  return arg2.multiply(*this);
672 
673  _knuminteger * tmp_num = new _knuminteger();
674 
675  mpz_mul(tmp_num->_mpz, _mpz,
676  dynamic_cast<_knuminteger const &>(arg2)._mpz);
677 
678  return tmp_num;
679 }
680 
681 _knumber * _knumfraction::multiply(_knumber const & arg2) const
682 {
683  if (arg2.type() == IntegerType) {
684  // need to cast arg2 to fraction
685  _knumfraction tmp_num(arg2);
686  return tmp_num.multiply(*this);
687  }
688 
689 
690  if (arg2.type() == FloatType || arg2.type() == SpecialType)
691  return arg2.multiply(*this);
692 
693  _knumfraction * tmp_num = new _knumfraction();
694 
695  mpq_mul(tmp_num->_mpq, _mpq,
696  dynamic_cast<_knumfraction const &>(arg2)._mpq);
697 
698  return tmp_num;
699 }
700 
701 _knumber *_knumfloat::multiply(_knumber const & arg2) const
702 {
703  if (arg2.type() == SpecialType)
704  return arg2.multiply(*this);
705  if (arg2.type() == IntegerType &&
706  mpz_cmp_si(dynamic_cast<_knuminteger const &>(arg2)._mpz,0) == 0)
707  // if arg2 == 0 return integer 0!!
708  return new _knuminteger(0);
709 
710  if (arg2.type() != FloatType) {
711  // need to cast arg2 to float
712  _knumfloat tmp_num(arg2);
713  return tmp_num.multiply(*this);
714  }
715 
716  _knumfloat * tmp_num = new _knumfloat();
717 
718  mpf_mul(tmp_num->_mpf, _mpf,
719  dynamic_cast<_knumfloat const &>(arg2)._mpf);
720 
721  return tmp_num;
722 }
723 
724 
725 
726 
727 
728 _knumber * _knumber::divide(_knumber const & arg2) const
729 {
730  _knumber * tmp_num = arg2.reciprocal();
731  _knumber * rslt_num = this->multiply(*tmp_num);
732 
733  delete tmp_num;
734 
735  return rslt_num;
736 }
737 
738 _knumber *_knumfloat::divide(_knumber const & arg2) const
739 {
740  if(mpf_cmp_si(_mpf, 0) == 0) return new _knumerror(Infinity);
741 
742  // automatically casts arg2 to float
743  _knumfloat * tmp_num = new _knumfloat(arg2);
744 
745  mpf_div(tmp_num->_mpf, _mpf, tmp_num->_mpf);
746 
747  return tmp_num;
748 }
749 
750 
751 
752 
753 _knumber * _knumerror::power(_knumber const & exponent) const
754 {
755  static_cast<void>(exponent);
756  return new _knumerror(UndefinedNumber);
757 }
758 
759 _knumber * _knuminteger::power(_knumber const & exponent) const
760 {
761  if (exponent.type() == IntegerType) {
762 
763  mpz_t tmp_mpz;
764  mpz_init_set(tmp_mpz,
765  dynamic_cast<_knuminteger const &>(exponent)._mpz);
766 
767  if (! mpz_fits_ulong_p(tmp_mpz)) { // conversion wouldn't work, so
768  // use floats
769  mpz_clear(tmp_mpz);
770  // need to cast everything to float
771  _knumfloat tmp_num1(*this), tmp_num2(exponent);
772  return tmp_num1.power(tmp_num2);
773  }
774 
775  unsigned long int tmp_int = mpz_get_ui(tmp_mpz);
776  mpz_clear(tmp_mpz);
777 
778  _knuminteger * tmp_num = new _knuminteger();
779  mpz_pow_ui(tmp_num->_mpz, _mpz, tmp_int);
780  return tmp_num;
781  }
782  if (exponent.type() == FractionType) {
783  if (mpz_sgn(_mpz) < 0)
784  return new _knumerror(UndefinedNumber);
785  // GMP only supports few root functions, so we need to convert
786  // into signed long int
787  mpz_t tmp_mpz;
788  mpz_init_set(tmp_mpz,
789  mpq_denref(dynamic_cast<_knumfraction const &>(exponent)._mpq));
790 
791  if (! mpz_fits_ulong_p(tmp_mpz)) { // conversion wouldn't work, so
792  // use floats
793  mpz_clear(tmp_mpz);
794  // need to cast everything to float
795  _knumfloat tmp_num1(*this), tmp_num2(exponent);
796  return tmp_num1.power(tmp_num2);
797  }
798 
799  unsigned long int tmp_int = mpz_get_ui(tmp_mpz);
800  mpz_clear(tmp_mpz);
801 
802  // first check if result will be an integer
803  _knuminteger * tmp_num = new _knuminteger();
804  int flag = mpz_root(tmp_num->_mpz, _mpz, tmp_int);
805  if (flag == 0) { // result is not exact
806  delete tmp_num;
807  // need to cast everything to float
808  _knumfloat tmp_num1(*this), tmp_num2(exponent);
809  return tmp_num1.power(tmp_num2);
810  }
811 
812  // result is exact
813 
814  mpz_init_set(tmp_mpz,
815  mpq_numref(dynamic_cast<_knumfraction const &>(exponent)._mpq));
816 
817  if (! mpz_fits_ulong_p(tmp_mpz)) { // conversion wouldn't work, so
818  // use floats
819  mpz_clear(tmp_mpz);
820  // need to cast everything to float
821  _knumfloat tmp_num1(*this), tmp_num2(exponent);
822  return tmp_num1.power(tmp_num2);
823  }
824  tmp_int = mpz_get_ui(tmp_mpz);
825  mpz_clear(tmp_mpz);
826 
827  mpz_pow_ui(tmp_num->_mpz, tmp_num->_mpz, tmp_int);
828 
829  return tmp_num;
830  }
831  if (exponent.type() == FloatType) {
832  // need to cast everything to float
833  _knumfloat tmp_num(*this);
834  return tmp_num.power(exponent);
835  }
836 
837  return new _knumerror(Infinity);
838 }
839 
840 _knumber * _knumfraction::power(_knumber const & exponent) const
841 {
842  _knuminteger tmp_num = _knuminteger();
843 
844  mpz_set(tmp_num._mpz, mpq_numref(_mpq));
845  _knumber *numer = tmp_num.power(exponent);
846 
847  mpz_set(tmp_num._mpz, mpq_denref(_mpq));
848  _knumber *denom = tmp_num.power(exponent);
849 
850  _knumber *result = numer->divide(*denom);
851  delete numer;
852  delete denom;
853  return result;
854 }
855 
856 _knumber * _knumfloat::power(_knumber const & exponent) const
857 {
858  return new _knumfloat(pow(static_cast<double>(*this),
859  static_cast<double>(exponent)));
860 }
861 
862 
863 int _knumerror::compare(_knumber const &arg2) const
864 {
865  if (arg2.type() != SpecialType) {
866  switch(_error) {
867  case Infinity:
868  return 1;
869  case MinusInfinity:
870  return -1;
871  default:
872  return 1; // Not really o.k., but what should I return
873  }
874  }
875 
876  switch(_error) {
877  case Infinity:
878  if (dynamic_cast<_knumerror const &>(arg2)._error == Infinity)
879  // Infinity is larger than anything else, but itself
880  return 0;
881  return 1;
882  case MinusInfinity:
883  if (dynamic_cast<_knumerror const &>(arg2)._error == MinusInfinity)
884  // MinusInfinity is smaller than anything else, but itself
885  return 0;
886  return -1;
887  default:
888  if (dynamic_cast<_knumerror const &>(arg2)._error == UndefinedNumber)
889  // Undefined only equal to itself
890  return 0;
891  return -arg2.compare(*this);
892  }
893 }
894 
895 int _knuminteger::compare(_knumber const &arg2) const
896 {
897  if (arg2.type() != IntegerType)
898  return - arg2.compare(*this);
899 
900  return mpz_cmp(_mpz, dynamic_cast<_knuminteger const &>(arg2)._mpz);
901 }
902 
903 int _knumfraction::compare(_knumber const &arg2) const
904 {
905  if (arg2.type() != FractionType) {
906  if (arg2.type() == IntegerType) {
907  mpq_t tmp_frac;
908  mpq_init(tmp_frac);
909  mpq_set_z(tmp_frac,
910  dynamic_cast<_knuminteger const &>(arg2)._mpz);
911  int cmp_result = mpq_cmp(_mpq, tmp_frac);
912  mpq_clear(tmp_frac);
913  return cmp_result;
914  } else
915  return - arg2.compare(*this);
916  }
917 
918  return mpq_cmp(_mpq, dynamic_cast<_knumfraction const &>(arg2)._mpq);
919 }
920 
921 int _knumfloat::compare(_knumber const &arg2) const
922 {
923  if (arg2.type() != FloatType) {
924  mpf_t tmp_float;
925  if (arg2.type() == IntegerType) {
926  mpf_init(tmp_float);
927  mpf_set_z(tmp_float,
928  dynamic_cast<_knuminteger const &>(arg2)._mpz);
929  } else if (arg2.type() == FractionType) {
930  mpf_init(tmp_float);
931  mpf_set_q(tmp_float,
932  dynamic_cast<_knumfraction const &>(arg2)._mpq);
933  } else
934  return - arg2.compare(*this);
935 
936  int cmp_result = mpf_cmp(_mpf, tmp_float);
937  mpf_clear(tmp_float);
938  return cmp_result;
939  }
940 
941  return mpf_cmp(_mpf, dynamic_cast<_knumfloat const &>(arg2)._mpf);
942 }
943 
944 
945 
946 _knumerror::operator signed long int (void) const
947 {
948  // what would be the correct return values here?
949  if (_error == Infinity)
950  return 0;
951  if (_error == MinusInfinity)
952  return 0;
953  else // if (_error == UndefinedNumber)
954  return 0;
955 }
956 
957 _knumerror::operator unsigned long int (void) const
958 {
959  // what would be the correct return values here?
960  if (_error == Infinity)
961  return 0;
962  if (_error == MinusInfinity)
963  return 0;
964  else // if (_error == UndefinedNumber)
965  return 0;
966 }
967 
968 
969 _knuminteger::operator signed long int (void) const
970 {
971  return mpz_get_si(_mpz);
972 }
973 
974 _knumfraction::operator signed long int (void) const
975 {
976  return static_cast<signed long int>(mpq_get_d(_mpq));
977 }
978 
979 _knumfloat::operator signed long int (void) const
980 {
981  return mpf_get_si(_mpf);
982 }
983 
984 _knuminteger::operator unsigned long int (void) const
985 {
986  return mpz_get_ui(_mpz);
987 }
988 
989 _knumfraction::operator unsigned long int (void) const
990 {
991  return static_cast<unsigned long int>(mpq_get_d(_mpq));
992 }
993 
994 _knumfloat::operator unsigned long int (void) const
995 {
996  return mpf_get_ui(_mpf);
997 }
998 
999 
1000 
1001 _knumerror::operator double (void) const
1002 {
1003  if (_error == Infinity)
1004  return INFINITY;
1005  if (_error == MinusInfinity)
1006  return -INFINITY;
1007  else // if (_error == UndefinedNumber)
1008  return NAN;
1009 }
1010 
1011 _knuminteger::operator double (void) const
1012 {
1013  return mpz_get_d(_mpz);
1014 }
1015 
1016 _knumfraction::operator double (void) const
1017 {
1018  return mpq_get_d(_mpq);
1019 }
1020 
1021 _knumfloat::operator double (void) const
1022 {
1023  return mpf_get_d(_mpf);
1024 }
1025 
1026 
1027 
1028 
1029 _knuminteger * _knuminteger::intAnd(_knuminteger const &arg2) const
1030 {
1031  _knuminteger * tmp_num = new _knuminteger();
1032 
1033  mpz_and(tmp_num->_mpz, _mpz, arg2._mpz);
1034 
1035  return tmp_num;
1036 }
1037 
1038 _knuminteger * _knuminteger::intOr(_knuminteger const &arg2) const
1039 {
1040  _knuminteger * tmp_num = new _knuminteger();
1041 
1042  mpz_ior(tmp_num->_mpz, _mpz, arg2._mpz);
1043 
1044  return tmp_num;
1045 }
1046 
1047 _knumber * _knuminteger::mod(_knuminteger const &arg2) const
1048 {
1049  if(mpz_cmp_si(arg2._mpz, 0) == 0) return new _knumerror(UndefinedNumber);
1050 
1051  _knuminteger * tmp_num = new _knuminteger();
1052 
1053  mpz_mod(tmp_num->_mpz, _mpz, arg2._mpz);
1054 
1055  return tmp_num;
1056 }
1057 
1058 _knumber * _knuminteger::shift(_knuminteger const &arg2) const
1059 {
1060  mpz_t tmp_mpz;
1061 
1062  mpz_init_set (tmp_mpz, arg2._mpz);
1063 
1064  if (! mpz_fits_slong_p(tmp_mpz)) {
1065  mpz_clear(tmp_mpz);
1066  return new _knumerror(UndefinedNumber);
1067  }
1068 
1069  signed long int tmp_arg2 = mpz_get_si(tmp_mpz);
1070  mpz_clear(tmp_mpz);
1071 
1072 
1073  _knuminteger * tmp_num = new _knuminteger();
1074 
1075  if (tmp_arg2 > 0) // left shift
1076  mpz_mul_2exp(tmp_num->_mpz, _mpz, tmp_arg2);
1077  else // right shift
1078  mpz_tdiv_q_2exp(tmp_num->_mpz, _mpz, -tmp_arg2);
1079 
1080 
1081  return tmp_num;
1082 }
1083 

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.