• 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
181TQString 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
197TQString 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
209TQString 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
220TQString 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
237bool _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
317int _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
329int _knuminteger::sign(void) const
330{
331 return mpz_sgn(_mpz);
332}
333
334int _knumfraction::sign(void) const
335{
336 return mpq_sgn(_mpq);
337}
338
339int _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
347static 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
863int _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
895int _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
903int _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
921int _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.9.4
This website is maintained by Timothy Pearson.