File indexing completed on 2024-04-21 05:50:02

0001 /*
0002     SPDX-FileCopyrightText: 2001-2013 Evan Teran <evan.teran@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "knumber_error.h"
0008 #include "knumber_float.h"
0009 #include "knumber_fraction.h"
0010 #include "knumber_integer.h"
0011 #include <cmath> // for M_PI
0012 #include <config-kcalc.h>
0013 
0014 namespace detail
0015 {
0016 //------------------------------------------------------------------------------
0017 // Name:
0018 //------------------------------------------------------------------------------
0019 knumber_error::knumber_error(Error e)
0020     : error_(e)
0021 {
0022 }
0023 
0024 //------------------------------------------------------------------------------
0025 // Name:
0026 //------------------------------------------------------------------------------
0027 knumber_error::knumber_error(const QString &s)
0028 {
0029     if (s == QLatin1String("nan"))
0030         error_ = ERROR_UNDEFINED;
0031     else if (s == QLatin1String("inf"))
0032         error_ = ERROR_POS_INFINITY;
0033     else if (s == QLatin1String("-inf"))
0034         error_ = ERROR_NEG_INFINITY;
0035     else
0036         error_ = ERROR_UNDEFINED;
0037 }
0038 
0039 //------------------------------------------------------------------------------
0040 // Name:
0041 //------------------------------------------------------------------------------
0042 knumber_error::knumber_error()
0043     : error_(ERROR_UNDEFINED)
0044 {
0045 }
0046 
0047 //------------------------------------------------------------------------------
0048 // Name:
0049 //------------------------------------------------------------------------------
0050 knumber_error::~knumber_error() = default;
0051 
0052 //------------------------------------------------------------------------------
0053 // Name:
0054 //------------------------------------------------------------------------------
0055 knumber_error::knumber_error(const knumber_integer *)
0056     : error_(ERROR_UNDEFINED)
0057 {
0058 }
0059 
0060 //------------------------------------------------------------------------------
0061 // Name:
0062 //------------------------------------------------------------------------------
0063 knumber_error::knumber_error(const knumber_fraction *)
0064     : error_(ERROR_UNDEFINED)
0065 {
0066 }
0067 
0068 //------------------------------------------------------------------------------
0069 // Name:
0070 //------------------------------------------------------------------------------
0071 knumber_error::knumber_error(const knumber_float *)
0072     : error_(ERROR_UNDEFINED)
0073 {
0074 }
0075 
0076 //------------------------------------------------------------------------------
0077 // Name:
0078 //------------------------------------------------------------------------------
0079 knumber_error::knumber_error(const knumber_error *value)
0080     : error_(value->error_)
0081 {
0082 }
0083 
0084 //------------------------------------------------------------------------------
0085 // Name:
0086 //------------------------------------------------------------------------------
0087 QString knumber_error::toString(int precision) const
0088 {
0089     Q_UNUSED(precision);
0090 
0091     switch (error_) {
0092     case ERROR_POS_INFINITY:
0093         return QStringLiteral("inf");
0094     case ERROR_NEG_INFINITY:
0095         return QStringLiteral("-inf");
0096     case ERROR_UNDEFINED:
0097     default:
0098         return QStringLiteral("nan");
0099     }
0100 }
0101 
0102 //------------------------------------------------------------------------------
0103 // Name:
0104 //------------------------------------------------------------------------------
0105 knumber_base *knumber_error::add(knumber_base *rhs)
0106 {
0107     if (auto const p = dynamic_cast<knumber_integer *>(rhs)) {
0108         Q_UNUSED(p);
0109         return this;
0110     } else if (auto const p = dynamic_cast<knumber_float *>(rhs)) {
0111         Q_UNUSED(p);
0112         return this;
0113     } else if (auto const p = dynamic_cast<knumber_fraction *>(rhs)) {
0114         Q_UNUSED(p);
0115         return this;
0116     } else if (auto const p = dynamic_cast<knumber_error *>(rhs)) {
0117         if (error_ == ERROR_POS_INFINITY && p->error_ == ERROR_NEG_INFINITY) {
0118             error_ = ERROR_UNDEFINED;
0119         } else if (error_ == ERROR_NEG_INFINITY && p->error_ == ERROR_POS_INFINITY) {
0120             error_ = ERROR_UNDEFINED;
0121         } else if (p->error_ == ERROR_UNDEFINED) {
0122             error_ = ERROR_UNDEFINED;
0123         }
0124         return this;
0125     }
0126 
0127     Q_ASSERT(0);
0128     return nullptr;
0129 }
0130 
0131 //------------------------------------------------------------------------------
0132 // Name:
0133 //------------------------------------------------------------------------------
0134 knumber_base *knumber_error::sub(knumber_base *rhs)
0135 {
0136     if (auto const p = dynamic_cast<knumber_integer *>(rhs)) {
0137         Q_UNUSED(p);
0138         return this;
0139     } else if (auto const p = dynamic_cast<knumber_float *>(rhs)) {
0140         Q_UNUSED(p);
0141         return this;
0142     } else if (auto const p = dynamic_cast<knumber_fraction *>(rhs)) {
0143         Q_UNUSED(p);
0144         return this;
0145     } else if (auto const p = dynamic_cast<knumber_error *>(rhs)) {
0146         if (error_ == ERROR_POS_INFINITY && p->error_ == ERROR_POS_INFINITY) {
0147             error_ = ERROR_UNDEFINED;
0148         } else if (error_ == ERROR_NEG_INFINITY && p->error_ == ERROR_NEG_INFINITY) {
0149             error_ = ERROR_UNDEFINED;
0150         } else if (p->error_ == ERROR_UNDEFINED) {
0151             error_ = ERROR_UNDEFINED;
0152         }
0153         return this;
0154     }
0155 
0156     Q_ASSERT(0);
0157     return nullptr;
0158 }
0159 
0160 //------------------------------------------------------------------------------
0161 // Name:
0162 //------------------------------------------------------------------------------
0163 knumber_base *knumber_error::mul(knumber_base *rhs)
0164 {
0165     if (auto const p = dynamic_cast<knumber_integer *>(rhs)) {
0166         if (p->is_zero()) {
0167             error_ = ERROR_UNDEFINED;
0168         }
0169         return this;
0170     } else if (auto const p = dynamic_cast<knumber_float *>(rhs)) {
0171         if (p->is_zero()) {
0172             error_ = ERROR_UNDEFINED;
0173         }
0174         return this;
0175     } else if (auto const p = dynamic_cast<knumber_fraction *>(rhs)) {
0176         if (p->is_zero()) {
0177             error_ = ERROR_UNDEFINED;
0178         }
0179         return this;
0180     } else if (auto const p = dynamic_cast<knumber_error *>(rhs)) {
0181         if (error_ == ERROR_POS_INFINITY && p->error_ == ERROR_NEG_INFINITY) {
0182             error_ = ERROR_NEG_INFINITY;
0183         } else if (error_ == ERROR_NEG_INFINITY && p->error_ == ERROR_POS_INFINITY) {
0184             error_ = ERROR_NEG_INFINITY;
0185         } else if (error_ == ERROR_NEG_INFINITY && p->error_ == ERROR_NEG_INFINITY) {
0186             error_ = ERROR_POS_INFINITY;
0187         } else if (p->error_ == ERROR_UNDEFINED) {
0188             error_ = ERROR_UNDEFINED;
0189         }
0190         return this;
0191     }
0192 
0193     Q_ASSERT(0);
0194     return nullptr;
0195 }
0196 
0197 //------------------------------------------------------------------------------
0198 // Name:
0199 //------------------------------------------------------------------------------
0200 knumber_base *knumber_error::div(knumber_base *rhs)
0201 {
0202     if (auto const p = dynamic_cast<knumber_integer *>(rhs)) {
0203         Q_UNUSED(p);
0204         return this;
0205     } else if (auto const p = dynamic_cast<knumber_float *>(rhs)) {
0206         Q_UNUSED(p);
0207         return this;
0208     } else if (auto const p = dynamic_cast<knumber_fraction *>(rhs)) {
0209         Q_UNUSED(p);
0210         return this;
0211     } else if (auto const p = dynamic_cast<knumber_error *>(rhs)) {
0212         Q_UNUSED(p);
0213         error_ = ERROR_UNDEFINED;
0214         return this;
0215     }
0216 
0217     Q_ASSERT(0);
0218     return nullptr;
0219 }
0220 
0221 //------------------------------------------------------------------------------
0222 // Name:
0223 //------------------------------------------------------------------------------
0224 knumber_base *knumber_error::mod(knumber_base *rhs)
0225 {
0226     if (auto const p = dynamic_cast<knumber_integer *>(rhs)) {
0227         Q_UNUSED(p);
0228         return this;
0229     } else if (auto const p = dynamic_cast<knumber_float *>(rhs)) {
0230         Q_UNUSED(p);
0231         return this;
0232     } else if (auto const p = dynamic_cast<knumber_fraction *>(rhs)) {
0233         Q_UNUSED(p);
0234         return this;
0235     } else if (auto const p = dynamic_cast<knumber_error *>(rhs)) {
0236         Q_UNUSED(p);
0237         error_ = ERROR_UNDEFINED;
0238         return this;
0239     }
0240 
0241     Q_ASSERT(0);
0242     return nullptr;
0243 }
0244 
0245 //------------------------------------------------------------------------------
0246 // Name:
0247 //------------------------------------------------------------------------------
0248 knumber_base *knumber_error::pow(knumber_base *rhs)
0249 {
0250     if (auto const p = dynamic_cast<knumber_integer *>(rhs)) {
0251         Q_UNUSED(p);
0252         return this;
0253     } else if (auto const p = dynamic_cast<knumber_float *>(rhs)) {
0254         Q_UNUSED(p);
0255         return this;
0256     } else if (auto const p = dynamic_cast<knumber_fraction *>(rhs)) {
0257         Q_UNUSED(p);
0258         return this;
0259     } else if (auto const p = dynamic_cast<knumber_error *>(rhs)) {
0260         switch (error_) {
0261         case ERROR_POS_INFINITY:
0262             if (p->sign() > 0) {
0263                 return this;
0264             } else if (p->sign() < 0) {
0265                 auto n = new knumber_integer(0);
0266                 delete this;
0267                 return n;
0268             } else {
0269                 error_ = ERROR_UNDEFINED;
0270                 return this;
0271             }
0272             break;
0273         case ERROR_NEG_INFINITY:
0274             if (p->sign() > 0) {
0275                 error_ = ERROR_POS_INFINITY;
0276                 return this;
0277             } else if (p->sign() < 0) {
0278                 auto n = new knumber_integer(0);
0279                 delete this;
0280                 return n;
0281             } else {
0282                 error_ = ERROR_UNDEFINED;
0283                 return this;
0284             }
0285             break;
0286         case ERROR_UNDEFINED:
0287             return this;
0288         }
0289     }
0290 
0291     Q_ASSERT(0);
0292     return nullptr;
0293 }
0294 
0295 //------------------------------------------------------------------------------
0296 // Name:
0297 //------------------------------------------------------------------------------
0298 knumber_base *knumber_error::neg()
0299 {
0300     switch (error_) {
0301     case ERROR_POS_INFINITY:
0302         error_ = ERROR_NEG_INFINITY;
0303         break;
0304     case ERROR_NEG_INFINITY:
0305         error_ = ERROR_POS_INFINITY;
0306         break;
0307     case ERROR_UNDEFINED:
0308     default:
0309         break;
0310     }
0311 
0312     return this;
0313 }
0314 
0315 //------------------------------------------------------------------------------
0316 // Name:
0317 //------------------------------------------------------------------------------
0318 knumber_base *knumber_error::cmp()
0319 {
0320     error_ = ERROR_UNDEFINED;
0321     return this;
0322 }
0323 
0324 //------------------------------------------------------------------------------
0325 // Name:
0326 //------------------------------------------------------------------------------
0327 knumber_base *knumber_error::abs()
0328 {
0329     switch (error_) {
0330     case ERROR_NEG_INFINITY:
0331         error_ = ERROR_POS_INFINITY;
0332         break;
0333     case ERROR_POS_INFINITY:
0334     case ERROR_UNDEFINED:
0335     default:
0336         break;
0337     }
0338 
0339     return this;
0340 }
0341 
0342 //------------------------------------------------------------------------------
0343 // Name:
0344 //------------------------------------------------------------------------------
0345 knumber_base *knumber_error::sqrt()
0346 {
0347     switch (error_) {
0348     case ERROR_NEG_INFINITY:
0349         error_ = ERROR_UNDEFINED;
0350         break;
0351     case ERROR_POS_INFINITY:
0352     case ERROR_UNDEFINED:
0353     default:
0354         break;
0355     }
0356 
0357     return this;
0358 }
0359 
0360 //------------------------------------------------------------------------------
0361 // Name:
0362 //------------------------------------------------------------------------------
0363 knumber_base *knumber_error::cbrt()
0364 {
0365     return this;
0366 }
0367 
0368 //------------------------------------------------------------------------------
0369 // Name:
0370 //------------------------------------------------------------------------------
0371 knumber_base *knumber_error::factorial()
0372 {
0373     error_ = ERROR_UNDEFINED;
0374     return this;
0375 }
0376 
0377 //------------------------------------------------------------------------------
0378 // Name:
0379 //------------------------------------------------------------------------------
0380 knumber_base *knumber_error::sin()
0381 {
0382     error_ = ERROR_UNDEFINED;
0383     return this;
0384 }
0385 
0386 //------------------------------------------------------------------------------
0387 // Name:
0388 //------------------------------------------------------------------------------
0389 knumber_base *knumber_error::cos()
0390 {
0391     error_ = ERROR_UNDEFINED;
0392     return this;
0393 }
0394 
0395 //------------------------------------------------------------------------------
0396 // Name:
0397 //------------------------------------------------------------------------------
0398 knumber_base *knumber_error::tgamma()
0399 {
0400     error_ = ERROR_UNDEFINED;
0401     return this;
0402 }
0403 
0404 //------------------------------------------------------------------------------
0405 // Name:
0406 //------------------------------------------------------------------------------
0407 knumber_base *knumber_error::tan()
0408 {
0409     error_ = ERROR_UNDEFINED;
0410     return this;
0411 }
0412 
0413 //------------------------------------------------------------------------------
0414 // Name:
0415 //------------------------------------------------------------------------------
0416 knumber_base *knumber_error::asin()
0417 {
0418     error_ = ERROR_UNDEFINED;
0419     return this;
0420 }
0421 
0422 //------------------------------------------------------------------------------
0423 // Name:
0424 //------------------------------------------------------------------------------
0425 knumber_base *knumber_error::acos()
0426 {
0427     error_ = ERROR_UNDEFINED;
0428     return this;
0429 }
0430 
0431 //------------------------------------------------------------------------------
0432 // Name:
0433 //------------------------------------------------------------------------------
0434 knumber_base *knumber_error::atan()
0435 {
0436     switch (error_) {
0437     case ERROR_POS_INFINITY:
0438         delete this;
0439         return new knumber_float(M_PI / 2.0);
0440     case ERROR_NEG_INFINITY:
0441         delete this;
0442         return new knumber_float(-M_PI / 2.0);
0443     case ERROR_UNDEFINED:
0444     default:
0445         return this;
0446     }
0447 }
0448 
0449 //------------------------------------------------------------------------------
0450 // Name:
0451 //------------------------------------------------------------------------------
0452 knumber_base *knumber_error::sinh()
0453 {
0454     return this;
0455 }
0456 
0457 //------------------------------------------------------------------------------
0458 // Name:
0459 //------------------------------------------------------------------------------
0460 knumber_base *knumber_error::cosh()
0461 {
0462     error_ = ERROR_UNDEFINED;
0463     return this;
0464 }
0465 
0466 //------------------------------------------------------------------------------
0467 // Name:
0468 //------------------------------------------------------------------------------
0469 knumber_base *knumber_error::tanh()
0470 {
0471     if (sign() > 0) {
0472         delete this;
0473         return new knumber_integer(1);
0474     } else if (sign() < 0) {
0475         delete this;
0476         return new knumber_integer(-1);
0477     } else {
0478         return this;
0479     }
0480 }
0481 
0482 //------------------------------------------------------------------------------
0483 // Name:
0484 //------------------------------------------------------------------------------
0485 knumber_base *knumber_error::asinh()
0486 {
0487     return this;
0488 }
0489 
0490 //------------------------------------------------------------------------------
0491 // Name:
0492 //------------------------------------------------------------------------------
0493 knumber_base *knumber_error::acosh()
0494 {
0495     if (sign() < 0) {
0496         error_ = ERROR_UNDEFINED;
0497     }
0498 
0499     return this;
0500 }
0501 
0502 //------------------------------------------------------------------------------
0503 // Name:
0504 //------------------------------------------------------------------------------
0505 knumber_base *knumber_error::atanh()
0506 {
0507     error_ = ERROR_UNDEFINED;
0508     return this;
0509 }
0510 
0511 //------------------------------------------------------------------------------
0512 // Name:
0513 //------------------------------------------------------------------------------
0514 int knumber_error::compare(knumber_base *rhs)
0515 {
0516     if (auto const p = dynamic_cast<knumber_integer *>(rhs)) {
0517         if (sign() > 0) {
0518             return 1;
0519         } else {
0520             return -1;
0521         }
0522     } else if (auto const p = dynamic_cast<knumber_float *>(rhs)) {
0523         if (sign() > 0) {
0524             return 1;
0525         } else {
0526             return -1;
0527         }
0528     } else if (auto const p = dynamic_cast<knumber_fraction *>(rhs)) {
0529         if (sign() > 0) {
0530             return 1;
0531         } else {
0532             return -1;
0533         }
0534     } else if (auto const p = dynamic_cast<knumber_error *>(rhs)) {
0535         return sign() == p->sign();
0536     }
0537 
0538     Q_ASSERT(0);
0539     return 0;
0540 }
0541 
0542 //------------------------------------------------------------------------------
0543 // Name:
0544 //------------------------------------------------------------------------------
0545 knumber_base *knumber_error::clone()
0546 {
0547     return new knumber_error(this);
0548 }
0549 
0550 //------------------------------------------------------------------------------
0551 // Name:
0552 //------------------------------------------------------------------------------
0553 knumber_base *knumber_error::bitwise_and(knumber_base *rhs)
0554 {
0555     Q_UNUSED(rhs);
0556     error_ = ERROR_UNDEFINED;
0557     return this;
0558 }
0559 
0560 //------------------------------------------------------------------------------
0561 // Name:
0562 //------------------------------------------------------------------------------
0563 knumber_base *knumber_error::bitwise_xor(knumber_base *rhs)
0564 {
0565     Q_UNUSED(rhs);
0566     error_ = ERROR_UNDEFINED;
0567     return this;
0568 }
0569 
0570 //------------------------------------------------------------------------------
0571 // Name:
0572 //------------------------------------------------------------------------------
0573 knumber_base *knumber_error::bitwise_or(knumber_base *rhs)
0574 {
0575     Q_UNUSED(rhs);
0576     error_ = ERROR_UNDEFINED;
0577     return this;
0578 }
0579 
0580 //------------------------------------------------------------------------------
0581 // Name:
0582 //------------------------------------------------------------------------------
0583 knumber_base *knumber_error::bitwise_shift(knumber_base *rhs)
0584 {
0585     Q_UNUSED(rhs);
0586     error_ = ERROR_UNDEFINED;
0587     return this;
0588 }
0589 
0590 //------------------------------------------------------------------------------
0591 // Name:
0592 //------------------------------------------------------------------------------
0593 bool knumber_error::is_integer() const
0594 {
0595     return false;
0596 }
0597 
0598 //------------------------------------------------------------------------------
0599 // Name:
0600 //------------------------------------------------------------------------------
0601 bool knumber_error::is_zero() const
0602 {
0603     return false;
0604 }
0605 
0606 //------------------------------------------------------------------------------
0607 // Name:
0608 //------------------------------------------------------------------------------
0609 int knumber_error::sign() const
0610 {
0611     switch (error_) {
0612     case ERROR_POS_INFINITY:
0613         return +1;
0614     case ERROR_NEG_INFINITY:
0615         return -1;
0616     case ERROR_UNDEFINED:
0617     default:
0618         return 0;
0619     }
0620 }
0621 
0622 //------------------------------------------------------------------------------
0623 // Name:
0624 //------------------------------------------------------------------------------
0625 knumber_base *knumber_error::reciprocal()
0626 {
0627     error_ = ERROR_UNDEFINED;
0628     return this;
0629 }
0630 
0631 //------------------------------------------------------------------------------
0632 // Name:
0633 //------------------------------------------------------------------------------
0634 knumber_base *knumber_error::log2()
0635 {
0636     error_ = ERROR_UNDEFINED;
0637     return this;
0638 }
0639 
0640 //------------------------------------------------------------------------------
0641 // Name:
0642 //------------------------------------------------------------------------------
0643 knumber_base *knumber_error::log10()
0644 {
0645     error_ = ERROR_UNDEFINED;
0646     return this;
0647 }
0648 
0649 //------------------------------------------------------------------------------
0650 // Name:
0651 //------------------------------------------------------------------------------
0652 knumber_base *knumber_error::ln()
0653 {
0654     error_ = ERROR_UNDEFINED;
0655     return this;
0656 }
0657 
0658 //------------------------------------------------------------------------------
0659 // Name:
0660 //------------------------------------------------------------------------------
0661 knumber_base *knumber_error::ceil()
0662 {
0663     error_ = ERROR_UNDEFINED;
0664     return this;
0665 }
0666 
0667 //------------------------------------------------------------------------------
0668 // Name:
0669 //------------------------------------------------------------------------------
0670 knumber_base *knumber_error::floor()
0671 {
0672     error_ = ERROR_UNDEFINED;
0673     return this;
0674 }
0675 
0676 //------------------------------------------------------------------------------
0677 // Name:
0678 //------------------------------------------------------------------------------
0679 knumber_base *knumber_error::exp2()
0680 {
0681     error_ = ERROR_UNDEFINED;
0682     return this;
0683 }
0684 
0685 //------------------------------------------------------------------------------
0686 // Name:
0687 //------------------------------------------------------------------------------
0688 knumber_base *knumber_error::exp10()
0689 {
0690     error_ = ERROR_UNDEFINED;
0691     return this;
0692 }
0693 
0694 //------------------------------------------------------------------------------
0695 // Name:
0696 //------------------------------------------------------------------------------
0697 knumber_base *knumber_error::exp()
0698 {
0699     error_ = ERROR_UNDEFINED;
0700     return this;
0701 }
0702 
0703 //------------------------------------------------------------------------------
0704 // Name:
0705 //------------------------------------------------------------------------------
0706 quint64 knumber_error::toUint64() const
0707 {
0708     return 0;
0709 }
0710 
0711 //------------------------------------------------------------------------------
0712 // Name:
0713 //------------------------------------------------------------------------------
0714 qint64 knumber_error::toInt64() const
0715 {
0716     return 0;
0717 }
0718 
0719 //------------------------------------------------------------------------------
0720 // Name:
0721 //------------------------------------------------------------------------------
0722 knumber_base *knumber_error::bin(knumber_base *rhs)
0723 {
0724     Q_UNUSED(rhs);
0725     error_ = ERROR_UNDEFINED;
0726     return this;
0727 }
0728 
0729 }