diff --git a/kcalc.cpp b/kcalc.cpp
index 0f11b5c..2c7c330 100644
--- a/kcalc.cpp
+++ b/kcalc.cpp
@@ -1,2335 +1,2335 @@
/*
Copyright (C) 2001 - 2013 Evan Teran
evan.teran@gmail.com
Copyright (C) 2006 Michel Marti
mma@objectxp.com
Copyright (C) 1996 - 2000 Bernd Johannes Wuebben
wuebben@kde.org
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include "kcalc_version.h"
#include "kcalc.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "kcalc_bitset.h"
#include "kcalc_const_menu.h"
#include "kcalc_settings.h"
#include "kcalc_statusbar.h"
#include "kcalcdisplay.h"
namespace {
const char description[] = I18N_NOOP("KDE Calculator");
const int maxprecision = 1000;
}
//------------------------------------------------------------------------------
// Name: KCalculator
// Desc: constructor
//------------------------------------------------------------------------------
KCalculator::KCalculator(QWidget *parent) :
KXmlGuiWindow(parent),
shift_mode_(false),
hyp_mode_(false),
memory_num_(0.0),
constants_menu_(nullptr),
constants_(nullptr),
core() {
// central widget to contain all the elements
QWidget *const central = new QWidget(this);
central->setLayoutDirection(Qt::LeftToRight);
setCentralWidget(central);
KAcceleratorManager::setNoAccel(central);
// load science constants_ from xml-file
KCalcConstMenu::init_consts();
// setup interface (order is critical)
setupUi(central);
setupMainActions();
setStatusBar(new KCalcStatusBar(this));
createGUI();
setupKeys();
toolBar()->hide(); // hide by default
// create button groups
base_choose_group_ = new QButtonGroup(this);
base_choose_group_->setExclusive(true);
base_choose_group_->addButton(hexRadio, HexMode);
base_choose_group_->addButton(decRadio, DecMode);
base_choose_group_->addButton(octRadio, OctMode);
base_choose_group_->addButton(binRadio, BinMode);
connect(base_choose_group_, static_cast(&QButtonGroup::buttonClicked), this, &KCalculator::slotBaseSelected);
angle_choose_group_ = new QButtonGroup(this);
angle_choose_group_->setExclusive(true);
angle_choose_group_->addButton(degRadio, DegMode);
angle_choose_group_->addButton(radRadio, RadMode);
angle_choose_group_->addButton(gradRadio, GradMode);
connect(angle_choose_group_, static_cast(&QButtonGroup::buttonClicked), this, &KCalculator::slotAngleSelected);
// additional menu setup
constants_menu_ = createConstantsMenu();
menuBar()->insertMenu((menuBar()->actions)()[2], constants_menu_);
// misc setup
setColors();
setFonts();
// Show the result in the app's caption in taskbar (wishlist - bug #52858)
if (KCalcSettings::captionResult() == true) {
connect(calc_display, &KCalcDisplay::changedText, this, &KCalculator::setWindowTitle);
}
calc_display->changeSettings();
setPrecision();
updateGeometry();
layout()->setSizeConstraint(QLayout::SetFixedSize);
updateDisplay(UPDATE_FROM_CORE);
// misc settings
KCalcSettings::EnumCalculatorMode::type calculatorMode = KCalcSettings::calculatorMode();
switch (calculatorMode) {
case KCalcSettings::EnumCalculatorMode::science:
action_mode_science_->setChecked(true);
break;
case KCalcSettings::EnumCalculatorMode::statistics:
action_mode_statistic_->setChecked(true);
break;
case KCalcSettings::EnumCalculatorMode::numeral:
action_mode_numeral_->setChecked(true);
break;
case KCalcSettings::EnumCalculatorMode::simple:
default:
action_mode_simple_->setChecked(true);
}
setAngle();
setBase();
calc_display->setFocus();
}
//------------------------------------------------------------------------------
// Name: ~KCalculator
// Desc: deconstructor
//------------------------------------------------------------------------------
KCalculator::~KCalculator() {
KCalcSettings::self()->save();
}
//------------------------------------------------------------------------------
// Name: setupMainActions
// Desc: connects all of the basic actions
//------------------------------------------------------------------------------
void KCalculator::setupMainActions() {
// file menu
KStandardAction::quit(this, SLOT(close()), actionCollection());
// edit menu
KStandardAction::undo(calc_display, SLOT(slotHistoryBack()), actionCollection());
KStandardAction::redo(calc_display, SLOT(slotHistoryForward()), actionCollection());
KStandardAction::cut(calc_display, SLOT(slotCut()), actionCollection());
KStandardAction::copy(calc_display, SLOT(slotCopy()), actionCollection());
KStandardAction::paste(calc_display, SLOT(slotPaste()), actionCollection());
// mode menu
QActionGroup *modeGroup = new QActionGroup(this);
action_mode_simple_ = actionCollection()->add(QLatin1String("mode_simple"));
action_mode_simple_->setActionGroup(modeGroup);
action_mode_simple_->setText(i18n("Simple Mode"));
connect(action_mode_simple_, &KToggleAction::toggled, this, &KCalculator::slotSetSimpleMode);
action_mode_science_ = actionCollection()->add(QLatin1String("mode_science"));
action_mode_science_->setActionGroup(modeGroup);
action_mode_science_->setText(i18n("Science Mode"));
connect(action_mode_science_, &KToggleAction::toggled, this, &KCalculator::slotSetScienceMode);
action_mode_statistic_ = actionCollection()->add(QLatin1String("mode_statistics"));
action_mode_statistic_->setActionGroup(modeGroup);
action_mode_statistic_->setText(i18n("Statistic Mode"));
connect(action_mode_statistic_, &KToggleAction::toggled, this, &KCalculator::slotSetStatisticMode);
action_mode_numeral_ = actionCollection()->add(QLatin1String("mode_numeral"));
action_mode_numeral_->setActionGroup(modeGroup);
action_mode_numeral_->setText(i18n("Numeral System Mode"));
connect(action_mode_numeral_, &KToggleAction::toggled, this, &KCalculator::slotSetNumeralMode);
// settings menu
action_constants_show_ = actionCollection()->add(QLatin1String("show_constants"));
action_constants_show_->setText(i18n("Constants &Buttons"));
action_constants_show_->setChecked(true);
connect(action_constants_show_, &KToggleAction::toggled, this, &KCalculator::slotConstantsShow);
action_bitset_show_ = actionCollection()->add(QLatin1String("show_bitset"));
action_bitset_show_->setText(i18n("Show B&it Edit"));
action_bitset_show_->setChecked(true);
connect(action_bitset_show_, &KToggleAction::toggled, this, &KCalculator::slotBitsetshow);
KStandardAction::preferences(this, SLOT(showSettings()), actionCollection());
KStandardAction::keyBindings(guiFactory(), SLOT(configureShortcuts()), actionCollection());
}
//------------------------------------------------------------------------------
// Name: createConstantsMenu
// Desc: creates and returns a pointer to the constant menu
//------------------------------------------------------------------------------
KCalcConstMenu *KCalculator::createConstantsMenu() {
KCalcConstMenu *const menu = new KCalcConstMenu(i18n("&Constants"), this);
connect(menu, &KCalcConstMenu::triggeredConstant, this, &KCalculator::slotConstantToDisplay);
return menu;
}
//------------------------------------------------------------------------------
// Name: statusBar
// Desc: returns a pointer to the status bar
//------------------------------------------------------------------------------
KCalcStatusBar *KCalculator::statusBar() {
return static_cast(KXmlGuiWindow::statusBar());
}
//------------------------------------------------------------------------------
// Name: setupNumberKeys
// Desc: sets up number keys and related shortcuts
//------------------------------------------------------------------------------
void KCalculator::setupNumberKeys() {
num_button_group_ = new QButtonGroup(this);
connect(num_button_group_, static_cast(&QButtonGroup::buttonClicked), this, &KCalculator::slotNumberclicked);
num_button_group_->addButton(pb0, 0);
num_button_group_->addButton(pb1, 1);
num_button_group_->addButton(pb2, 2);
num_button_group_->addButton(pb3, 3);
num_button_group_->addButton(pb4, 4);
num_button_group_->addButton(pb5, 5);
num_button_group_->addButton(pb6, 6);
num_button_group_->addButton(pb7, 7);
num_button_group_->addButton(pb8, 8);
num_button_group_->addButton(pb9, 9);
num_button_group_->addButton(pbA, 0xA);
num_button_group_->addButton(pbB, 0xB);
num_button_group_->addButton(pbC, 0xC);
num_button_group_->addButton(pbD, 0xD);
num_button_group_->addButton(pbE, 0xE);
num_button_group_->addButton(pbF, 0xF);
connect(this, &KCalculator::switchShowAccels, pb0, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchShowAccels, pb1, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchShowAccels, pb2, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchShowAccels, pb3, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchShowAccels, pb4, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchShowAccels, pb5, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchShowAccels, pb6, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchShowAccels, pb7, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchShowAccels, pb8, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchShowAccels, pb9, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchShowAccels, pbA, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchShowAccels, pbB, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchShowAccels, pbC, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchShowAccels, pbD, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchShowAccels, pbE, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchShowAccels, pbF, &KCalcButton::slotSetAccelDisplayMode);
}
//------------------------------------------------------------------------------
// Name: setupRightKeypad
// Desc: sets up right keypad keys and related shortcuts
//------------------------------------------------------------------------------
void KCalculator::setupRightKeypad() {
connect(pbShift, &KCalcButton::toggled, this, &KCalculator::slotShifttoggled);
connect(this, &KCalculator::switchShowAccels, pbShift, &KCalcButton::slotSetAccelDisplayMode);
pbBackspace->setShortcut(QKeySequence(Qt::Key_Backspace));
new QShortcut(Qt::Key_PageUp, pbBackspace, SLOT(animateClick()));
connect(pbBackspace, &KCalcButton::clicked, this, &KCalculator::slotBackspaceclicked);
connect(this, &KCalculator::switchShowAccels, pbBackspace, &KCalcButton::slotSetAccelDisplayMode);
pbClear->setShortcut(QKeySequence(Qt::Key_Escape));
new QShortcut(Qt::Key_PageUp, pbClear, SLOT(animateClick()));
connect(pbClear, &KCalcButton::clicked, this, &KCalculator::slotClearclicked);
connect(this, &KCalculator::switchShowAccels, pbClear, &KCalcButton::slotSetAccelDisplayMode);
pbAllClear->setShortcut(QKeySequence(Qt::Key_Delete));
new QShortcut(Qt::Key_PageDown, pbAllClear, SLOT(animateClick()));
connect(pbAllClear, &KCalcButton::clicked, this, &KCalculator::slotAllClearclicked);
connect(this, &KCalculator::switchShowAccels, pbAllClear, &KCalcButton::slotSetAccelDisplayMode);
pbParenOpen->setShortcut(QKeySequence(Qt::Key_ParenLeft));
connect(pbParenOpen, &KCalcButton::clicked, this, &KCalculator::slotParenOpenclicked);
connect(this, &KCalculator::switchShowAccels, pbParenOpen, &KCalcButton::slotSetAccelDisplayMode);
pbParenClose->setShortcut(QKeySequence(Qt::Key_ParenRight));
connect(pbParenClose, &KCalcButton::clicked, this, &KCalculator::slotParenCloseclicked);
connect(this, &KCalculator::switchShowAccels, pbParenClose, &KCalcButton::slotSetAccelDisplayMode);
pbMemRecall->setDisabled(true); // nothing in memory at start
connect(pbMemRecall, &KCalcButton::clicked, this, &KCalculator::slotMemRecallclicked);
connect(this, &KCalculator::switchShowAccels, pbMemRecall, &KCalcButton::slotSetAccelDisplayMode);
connect(pbMemClear, &KCalcButton::clicked, this, &KCalculator::slotMemClearclicked);
connect(this, &KCalculator::switchShowAccels, pbMemClear, &KCalcButton::slotSetAccelDisplayMode);
pbMemPlusMinus->addMode(ModeNormal, i18nc("Add display to memory", "M+"), i18n("Add display to memory"));
pbMemPlusMinus->addMode(ModeShift, i18nc("Subtract from memory", "M\xe2\x88\x92"), i18n("Subtract from memory"));
connect(pbMemPlusMinus, &KCalcButton::clicked, this, &KCalculator::slotMemPlusMinusclicked);
connect(this, &KCalculator::switchShowAccels, pbMemPlusMinus, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchMode, pbMemPlusMinus, &KCalcButton::slotSetMode);
connect(pbMemStore, &KCalcButton::clicked, this, &KCalculator::slotMemStoreclicked);
connect(this, &KCalculator::switchShowAccels, pbMemStore, &KCalcButton::slotSetAccelDisplayMode);
pbPercent->setShortcut(QKeySequence(Qt::Key_Percent));
connect(pbPercent, &KCalcButton::clicked, this, &KCalculator::slotPercentclicked);
connect(this, &KCalculator::switchShowAccels, pbPercent, &KCalcButton::slotSetAccelDisplayMode);
pbPlusMinus->setShortcut(QKeySequence(Qt::Key_Backslash));
connect(pbPlusMinus, &KCalcButton::clicked, this, &KCalculator::slotPlusMinusclicked);
connect(this, &KCalculator::switchShowAccels, pbPlusMinus, &KCalcButton::slotSetAccelDisplayMode);
}
//------------------------------------------------------------------------------
// Name: setupNumericKeypad
// Desc: sets up numeric keys and related shortcuts
//------------------------------------------------------------------------------
void KCalculator::setupNumericKeypad() {
pbCube->addMode(ModeNormal, i18nc("Third power", "x3"), i18n("Third power"));
pbCube->addMode(ModeShift, QLatin1String("3√x"), i18n("Cube root"));
connect(pbCube, &KCalcButton::clicked, this, &KCalculator::slotCubeclicked);
connect(this, &KCalculator::switchShowAccels, pbCube, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchMode, pbCube, &KCalcButton::slotSetMode);
pbDivision->setShortcut(QKeySequence(Qt::Key_Slash));
new QShortcut(Qt::Key_division, pbDivision, SLOT(animateClick()));
connect(pbDivision, &KCalcButton::clicked, this, &KCalculator::slotDivisionclicked);
connect(this, &KCalculator::switchShowAccels, pbDivision, &KCalcButton::slotSetAccelDisplayMode);
pbMultiplication->setShortcut(QKeySequence(Qt::Key_Asterisk));
new QShortcut(Qt::Key_X, pbMultiplication, SLOT(animateClick()));
new QShortcut(Qt::Key_multiply, pbMultiplication, SLOT(animateClick()));
connect(pbMultiplication, &KCalcButton::clicked, this, &KCalculator::slotMultiplicationclicked);
connect(this, &KCalculator::switchShowAccels, pbMultiplication, &KCalcButton::slotSetAccelDisplayMode);
pbMinus->setShortcut(QKeySequence(Qt::Key_Minus));
connect(pbMinus, &KCalcButton::clicked, this, &KCalculator::slotMinusclicked);
connect(this, &KCalculator::switchShowAccels, pbMinus, &KCalcButton::slotSetAccelDisplayMode);
pbPlus->setShortcut(QKeySequence(Qt::Key_Plus));
connect(pbPlus, &KCalcButton::clicked, this, &KCalculator::slotPlusclicked);
connect(this, &KCalculator::switchShowAccels, pbPlus, &KCalcButton::slotSetAccelDisplayMode);
// set decimal separator from locale
pbPeriod->setText(QString(QLocale().decimalPoint()));
pbPeriod->setShortcut(QString(QLocale().decimalPoint()));
// add shortcut for the other decimal separator (point or comma)
if (QLocale().decimalPoint() == QLatin1Char('.')) {
new QShortcut(Qt::Key_Comma, pbPeriod, SLOT(animateClick()));
} else if (QLocale().decimalPoint() == QLatin1Char(',')) {
new QShortcut(Qt::Key_Period, pbPeriod, SLOT(animateClick()));
}
connect(pbPeriod, &KCalcButton::clicked, this, &KCalculator::slotPeriodclicked);
connect(this, &KCalculator::switchShowAccels, pbPeriod, &KCalcButton::slotSetAccelDisplayMode);
pbEqual->setShortcut(QKeySequence(Qt::Key_Enter));
new QShortcut(Qt::Key_Equal, pbEqual, SLOT(animateClick()));
new QShortcut(Qt::Key_Return, pbEqual, SLOT(animateClick()));
connect(pbEqual, &KCalcButton::clicked, this, &KCalculator::slotEqualclicked);
connect(this, &KCalculator::switchShowAccels, pbEqual, &KCalcButton::slotSetAccelDisplayMode);
}
//------------------------------------------------------------------------------
// Name: setupLogicKeys
// Desc: sets up logic keys and related shortcuts
//------------------------------------------------------------------------------
void KCalculator::setupLogicKeys() {
logic_buttons_.append(pbAND);
logic_buttons_.append(pbOR);
logic_buttons_.append(pbXOR);
logic_buttons_.append(pbLsh);
logic_buttons_.append(pbRsh);
logic_buttons_.append(pbCmp);
pbAND->setShortcut(QKeySequence(Qt::Key_Ampersand));
connect(this, &KCalculator::switchShowAccels, pbAND, &KCalcButton::slotSetAccelDisplayMode);
connect(pbAND, &KCalcButton::clicked, this, &KCalculator::slotANDclicked);
pbOR->setShortcut(QKeySequence(Qt::Key_Bar));
connect(this, &KCalculator::switchShowAccels, pbOR, &KCalcButton::slotSetAccelDisplayMode);
connect(pbOR, &KCalcButton::clicked, this, &KCalculator::slotORclicked);
connect(this, &KCalculator::switchShowAccels, pbXOR, &KCalcButton::slotSetAccelDisplayMode);
connect(pbXOR, &KCalcButton::clicked, this, &KCalculator::slotXORclicked);
pbLsh->setShortcut(QKeySequence(Qt::Key_Less));
connect(this, &KCalculator::switchShowAccels, pbLsh, &KCalcButton::slotSetAccelDisplayMode);
connect(pbLsh, &KCalcButton::clicked, this, &KCalculator::slotLeftShiftclicked);
pbRsh->setShortcut(QKeySequence(Qt::Key_Greater));
connect(this, &KCalculator::switchShowAccels, pbRsh, &KCalcButton::slotSetAccelDisplayMode);
connect(pbRsh, &KCalcButton::clicked, this, &KCalculator::slotRightShiftclicked);
pbCmp->setShortcut(QKeySequence(Qt::Key_AsciiTilde));
connect(this, &KCalculator::switchShowAccels, pbCmp, &KCalcButton::slotSetAccelDisplayMode);
connect(pbCmp, &KCalcButton::clicked, this, &KCalculator::slotNegateclicked);
}
//------------------------------------------------------------------------------
// Name: setupLogicKeys
// Desc: sets up scientific keys and related shortcuts
//------------------------------------------------------------------------------
void KCalculator::setupScientificKeys() {
scientific_buttons_.append(pbHyp);
scientific_buttons_.append(pbSin);
scientific_buttons_.append(pbCos);
scientific_buttons_.append(pbTan);
scientific_buttons_.append(pbLog);
scientific_buttons_.append(pbLn);
connect(this, &KCalculator::switchShowAccels, pbHyp, &KCalcButton::slotSetAccelDisplayMode);
connect(pbHyp, &KCalcButton::toggled, this, &KCalculator::slotHyptoggled);
pbSin->addMode(ModeNormal, i18nc("Sine", "Sin"), i18n("Sine"));
pbSin->addMode(ModeShift, i18nc("Arc sine", "Asin"), i18n("Arc sine"));
pbSin->addMode(ModeHyperbolic, i18nc("Hyperbolic sine", "Sinh"), i18n("Hyperbolic sine"));
pbSin->addMode(ButtonModeFlags(ModeShift | ModeHyperbolic), i18nc("Inverse hyperbolic sine", "Asinh"), i18n("Inverse hyperbolic sine"));
connect(this, &KCalculator::switchShowAccels, pbSin, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchMode, pbSin, &KCalcButton::slotSetMode);
connect(pbSin, &KCalcButton::clicked, this, &KCalculator::slotSinclicked);
pbCos->addMode(ModeNormal, i18nc("Cosine", "Cos"), i18n("Cosine"));
pbCos->addMode(ModeShift, i18nc("Arc cosine", "Acos"), i18n("Arc cosine"));
pbCos->addMode(ModeHyperbolic, i18nc("Hyperbolic cosine", "Cosh"), i18n("Hyperbolic cosine"));
pbCos->addMode(ButtonModeFlags(ModeShift | ModeHyperbolic), i18nc("Inverse hyperbolic cosine", "Acosh"), i18n("Inverse hyperbolic cosine"));
connect(this, &KCalculator::switchShowAccels, pbCos, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchMode, pbCos, &KCalcButton::slotSetMode);
connect(pbCos, &KCalcButton::clicked, this, &KCalculator::slotCosclicked);
pbTan->addMode(ModeNormal, i18nc("Tangent", "Tan"), i18n("Tangent"));
pbTan->addMode(ModeShift, i18nc("Arc tangent", "Atan"), i18n("Arc tangent"));
pbTan->addMode(ModeHyperbolic, i18nc("Hyperbolic tangent", "Tanh"), i18n("Hyperbolic tangent"));
pbTan->addMode(ButtonModeFlags(ModeShift | ModeHyperbolic), i18nc("Inverse hyperbolic tangent", "Atanh"), i18n("Inverse hyperbolic tangent"));
connect(this, &KCalculator::switchShowAccels, pbTan, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchMode, pbTan, &KCalcButton::slotSetMode);
connect(pbTan, &KCalcButton::clicked, this, &KCalculator::slotTanclicked);
pbLog->addMode(ModeNormal, i18nc("Logarithm to base 10", "Log"), i18n("Logarithm to base 10"));
pbLog->addMode(ModeShift, i18nc("10 to the power of x", "10x"), i18n("10 to the power of x"));
connect(this, &KCalculator::switchShowAccels, pbLog, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchMode, pbLog, &KCalcButton::slotSetMode);
connect(pbLog, &KCalcButton::clicked, this, &KCalculator::slotLogclicked);
pbLn->addMode(ModeNormal, i18nc("Natural log", "Ln"), i18n("Natural log"));
pbLn->addMode(ModeShift, i18nc("Exponential function", "ex"), i18n("Exponential function"));
connect(this, &KCalculator::switchShowAccels, pbLn, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchMode, pbLn, &KCalcButton::slotSetMode);
connect(pbLn, &KCalcButton::clicked, this, &KCalculator::slotLnclicked);
}
//------------------------------------------------------------------------------
// Name: setupStatisticKeys
// Desc: sets up statistical keys and related shortcuts
//------------------------------------------------------------------------------
void KCalculator::setupStatisticKeys() {
stat_buttons_.append(pbNData);
stat_buttons_.append(pbMean);
stat_buttons_.append(pbSd);
stat_buttons_.append(pbMed);
stat_buttons_.append(pbDat);
stat_buttons_.append(pbCSt);
pbNData->addMode(ModeNormal, i18nc("Number of data entered", "N"), i18n("Number of data entered"));
pbNData->addMode(ModeShift, QString::fromUtf8("\xce\xa3") + QLatin1Char('x'), i18n("Sum of all data items"));
connect(this, &KCalculator::switchShowAccels, pbNData, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchMode, pbNData, &KCalcButton::slotSetMode);
connect(pbNData, &KCalcButton::clicked, this, &KCalculator::slotStatNumclicked);
pbMean->addMode(ModeNormal, i18nc("Mean", "Mea"), i18n("Mean"));
pbMean->addMode(ModeShift, QString::fromUtf8("\xce\xa3") + QLatin1String("x2"), i18n("Sum of all data items squared"));
connect(this, &KCalculator::switchShowAccels, pbMean, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchMode, pbMean, &KCalcButton::slotSetMode);
connect(pbMean, &KCalcButton::clicked, this, &KCalculator::slotStatMeanclicked);
pbSd->addMode(ModeNormal, QString::fromUtf8("\xcf\x83") + QLatin1String("N"), i18n("Standard deviation"));
pbSd->addMode(ModeShift, QString::fromUtf8("\xcf\x83") + QLatin1String("N-1"), i18n("Sample standard deviation"));
connect(this, &KCalculator::switchShowAccels, pbSd, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchMode, pbSd, &KCalcButton::slotSetMode);
connect(pbSd, &KCalcButton::clicked, this, &KCalculator::slotStatStdDevclicked);
connect(this, &KCalculator::switchShowAccels, pbMed, &KCalcButton::slotSetAccelDisplayMode);
connect(pbMed, &KCalcButton::clicked, this, &KCalculator::slotStatMedianclicked);
pbDat->addMode(ModeNormal, i18nc("Enter data", "Dat"), i18n("Enter data"));
pbDat->addMode(ModeShift, i18nc("Delete last data item", "CDat"), i18n("Delete last data item"));
connect(this, &KCalculator::switchShowAccels, pbDat, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchMode, pbDat, &KCalcButton::slotSetMode);
connect(pbDat, &KCalcButton::clicked, this, &KCalculator::slotStatDataInputclicked);
connect(this, &KCalculator::switchShowAccels, pbCSt, &KCalcButton::slotSetAccelDisplayMode);
connect(pbCSt, &KCalcButton::clicked, this, &KCalculator::slotStatClearDataclicked);
}
//------------------------------------------------------------------------------
// Name: setupConstantsKeys
// Desc: sets up constants keys and related shortcuts
//------------------------------------------------------------------------------
void KCalculator::setupConstantsKeys() {
const_buttons_.append(pbC1);
const_buttons_.append(pbC2);
const_buttons_.append(pbC3);
const_buttons_.append(pbC4);
const_buttons_.append(pbC5);
const_buttons_.append(pbC6);
pbC1->setButtonNumber(0);
connect(this, &KCalculator::switchShowAccels, pbC1, &KCalcConstButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchMode, pbC1, &KCalcConstButton::slotSetMode);
connect(pbC1, &KCalcConstButton::clicked, this, &KCalculator::slotConstclicked);
pbC2->setButtonNumber(1);
connect(this, &KCalculator::switchShowAccels, pbC2, &KCalcConstButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchMode, pbC2, &KCalcConstButton::slotSetMode);
connect(pbC2, &KCalcConstButton::clicked, this, &KCalculator::slotConstclicked);
pbC3->setButtonNumber(2);
connect(this, &KCalculator::switchShowAccels, pbC3, &KCalcConstButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchMode, pbC3, &KCalcConstButton::slotSetMode);
connect(pbC3, &KCalcConstButton::clicked, this, &KCalculator::slotConstclicked);
pbC4->setButtonNumber(3);
connect(this, &KCalculator::switchShowAccels, pbC4, &KCalcConstButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchMode, pbC4, &KCalcConstButton::slotSetMode);
connect(pbC4, &KCalcConstButton::clicked, this, &KCalculator::slotConstclicked);
pbC5->setButtonNumber(4);
connect(this, &KCalculator::switchShowAccels, pbC5, &KCalcConstButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchMode, pbC5, &KCalcConstButton::slotSetMode);
connect(pbC5, &KCalcConstButton::clicked, this, &KCalculator::slotConstclicked);
pbC6->setButtonNumber(5);
connect(this, &KCalculator::switchShowAccels, pbC6, &KCalcConstButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchMode, pbC6, &KCalcConstButton::slotSetMode);
connect(pbC6, &KCalcConstButton::clicked, this, &KCalculator::slotConstclicked);
changeButtonNames();
}
//------------------------------------------------------------------------------
// Name: setupMiscKeys
// Desc: sets up misc keys and related shortcuts
//------------------------------------------------------------------------------
void KCalculator::setupMiscKeys() {
pbMod->addMode(ModeNormal, i18nc("Modulo", "Mod"), i18n("Modulo"));
pbMod->addMode(ModeShift, i18nc("Integer division", "IntDiv"), i18n("Integer division"));
connect(this, &KCalculator::switchMode, pbMod, &KCalcButton::slotSetMode);
connect(this, &KCalculator::switchShowAccels, pbMod, &KCalcButton::slotSetAccelDisplayMode);
pbMod->setShortcut(QKeySequence(Qt::Key_Colon));
connect(pbMod, &KCalcButton::clicked, this, &KCalculator::slotModclicked);
pbReci->addMode(ModeNormal, i18nc("Reciprocal", "1/x"), i18n("Reciprocal"));
pbReci->addMode(ModeShift, i18nc("n Choose m", "nCm"), i18n("n Choose m"));
connect(this, &KCalculator::switchMode, pbReci, &KCalcButton::slotSetMode);
connect(this, &KCalculator::switchShowAccels, pbReci, &KCalcButton::slotSetAccelDisplayMode);
connect(pbReci, &KCalcButton::clicked, this, &KCalculator::slotReciclicked);
pbFactorial->addMode(ModeNormal, i18nc("Factorial", "x!"), i18n("Factorial"));
pbFactorial->addMode(ModeShift, QLatin1String("Γ"), i18n("Gamma"));
pbFactorial->setShortcut(QKeySequence(Qt::Key_Exclam));
connect(this, &KCalculator::switchShowAccels, pbFactorial, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchMode, pbFactorial, &KCalcButton::slotSetMode);
connect(pbFactorial, &KCalcButton::clicked, this, &KCalculator::slotFactorialclicked);
pbSquare->addMode(ModeNormal, i18nc("Square", "x2"), i18n("Square"));
pbSquare->addMode(ModeShift, QLatin1String("√x"), i18n("Square root"));
pbSquare->setShortcut(QKeySequence(Qt::Key_BracketLeft));
new QShortcut(Qt::Key_twosuperior, pbSquare, SLOT(animateClick()));
connect(this, &KCalculator::switchShowAccels, pbSquare, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchMode, pbSquare, &KCalcButton::slotSetMode);
connect(pbSquare, &KCalcButton::clicked, this, &KCalculator::slotSquareclicked);
pbPower->addMode(ModeNormal, i18nc("x to the power of y", "xy"), i18n("x to the power of y"));
pbPower->addMode(ModeShift, i18nc("x to the power of 1/y", "x1/y"), i18n("x to the power of 1/y"));
connect(this, &KCalculator::switchShowAccels, pbPower, &KCalcButton::slotSetAccelDisplayMode);
connect(this, &KCalculator::switchMode, pbPower, &KCalcButton::slotSetMode);
pbPower->setShortcut(QKeySequence(Qt::Key_AsciiCircum));
connect(pbPower, &KCalcButton::clicked, this, &KCalculator::slotPowerclicked);
pbEE->addMode(ModeNormal, QLatin1String("x" "\xb7" "10y"), i18n("Exponent"));
connect(this, &KCalculator::switchShowAccels, pbEE, &KCalcButton::slotSetAccelDisplayMode);
connect(pbEE, &KCalcButton::clicked, this, &KCalculator::slotEEclicked);
}
//------------------------------------------------------------------------------
// Name: createConstantsMenu
// Desc: additional setup for button keys
// NOTE: all alphanumeric shorts set in ui file
//------------------------------------------------------------------------------
void KCalculator::setupKeys() {
setupNumberKeys();
setupRightKeypad();
setupNumericKeypad();
setupLogicKeys();
setupScientificKeys();
setupStatisticKeys();
setupConstantsKeys();
setupMiscKeys();
// other button lists
function_button_list_.append(pbHyp);
function_button_list_.append(pbShift);
function_button_list_.append(pbEE);
function_button_list_.append(pbSin);
function_button_list_.append(pbPlusMinus);
function_button_list_.append(pbCos);
function_button_list_.append(pbReci);
function_button_list_.append(pbTan);
function_button_list_.append(pbFactorial);
function_button_list_.append(pbLog);
function_button_list_.append(pbSquare);
function_button_list_.append(pbLn);
function_button_list_.append(pbPower);
function_button_list_.append(pbCube);
mem_button_list_.append(pbMemRecall);
mem_button_list_.append(pbMemPlusMinus);
mem_button_list_.append(pbMemStore);
mem_button_list_.append(pbMemClear);
mem_button_list_.append(pbClear);
mem_button_list_.append(pbAllClear);
operation_button_list_.append(pbMultiplication);
operation_button_list_.append(pbParenOpen);
operation_button_list_.append(pbParenClose);
operation_button_list_.append(pbAND);
operation_button_list_.append(pbDivision);
operation_button_list_.append(pbOR);
operation_button_list_.append(pbXOR);
operation_button_list_.append(pbPlus);
operation_button_list_.append(pbMinus);
operation_button_list_.append(pbLsh);
operation_button_list_.append(pbRsh);
operation_button_list_.append(pbPeriod);
operation_button_list_.append(pbEqual);
operation_button_list_.append(pbPercent);
operation_button_list_.append(pbCmp);
operation_button_list_.append(pbMod);
}
//------------------------------------------------------------------------------
// Name: updateGeometry
// Desc: makes all the buttons have reasonable sizes
//------------------------------------------------------------------------------
void KCalculator::updateGeometry() {
const QSize em = pbAND->fontMetrics().size(0, QLatin1String("M"));
int margin = QApplication::style()->pixelMetric(QStyle::PM_ButtonMargin, 0, 0);
margin = qMax(qMin(margin / 2, 3), 3);
// left pad
foreach(QObject *obj, leftPad->children()) {
if (KCalcButton *const button = qobject_cast(obj)) {
button->setFixedWidth(em.width() * 4 + margin * 2);
button->installEventFilter(this);
}
}
// right pad
foreach(QObject *obj, rightPad->children()) {
KCalcButton *const button = qobject_cast(obj);
// let Shift expand freely
if (button && button != pbShift) {
button->setFixedWidth(em.width() * 3 + margin * 2);
button->installEventFilter(this);
}
}
// numeric pad
foreach(QObject *obj, numericPad->children()) {
if (KCalcButton *const button = qobject_cast(obj)) {
// let pb0 expand freely
if (button != pb0) {
button->setFixedWidth(em.width() * 3 + margin * 2);
}
button->installEventFilter(this);
}
}
}
//------------------------------------------------------------------------------
// Name: slotConstantToDisplay
// Desc: inserts a constant
//------------------------------------------------------------------------------
void KCalculator::slotConstantToDisplay(const science_constant &const_chosen) {
QString val = const_chosen.value;
val.replace(QLatin1Char('.'), KNumber::decimalSeparator());
calc_display->setAmount(KNumber(val));
updateDisplay({});
}
//------------------------------------------------------------------------------
// Name: slotBaseSelected
// Desc: changes the selected numeric base
//------------------------------------------------------------------------------
void KCalculator::slotBaseSelected(int base) {
int current_base;
// set display & statusbar (if item exist in statusbar)
statusBar()->setBase(base);
switch (base) {
case BinMode:
current_base = calc_display->setBase(NumBase(2));
calc_display->setStatusText(BaseField, QLatin1String("Bin"));
break;
case OctMode:
current_base = calc_display->setBase(NumBase(8));
calc_display->setStatusText(BaseField, QLatin1String("Oct"));
break;
case DecMode:
current_base = calc_display->setBase(NumBase(10));
calc_display->setStatusText(BaseField, QLatin1String("Dec"));
break;
case HexMode:
current_base = calc_display->setBase(NumBase(16));
calc_display->setStatusText(BaseField, QLatin1String("Hex"));
break;
default:
calc_display->setStatusText(BaseField, QLatin1String("Error"));
return;
}
// Enable the buttons available in this base
for (int i = 0; i < current_base; ++i) {
(num_button_group_->buttons()[i])->setEnabled(true);
}
// Disable the buttons not available in this base
for (int i = current_base; i < 16; ++i) {
(num_button_group_->buttons()[i])->setEnabled(false);
}
// Only enable the decimal point in decimal
pbPeriod->setEnabled(current_base == NB_DECIMAL);
// Only enable the x*10^y button in decimal
pbEE->setEnabled(current_base == NB_DECIMAL);
// Disable buttons that make only sense with floating point numbers
if (current_base != NB_DECIMAL) {
foreach(QAbstractButton *btn, scientific_buttons_) {
btn->setEnabled(false);
}
} else {
foreach(QAbstractButton *btn, scientific_buttons_) {
btn->setEnabled(true);
}
}
KCalcSettings::setBaseMode(base);
}
//------------------------------------------------------------------------------
// Name: keyPressEvent
// Desc: handles keypress events
//------------------------------------------------------------------------------
void KCalculator::keyPressEvent(QKeyEvent *e) {
// Fix for bug #314586
// Basically, on some keyboards such as French, even though the decimal separator
- // is "," the numeric keypad has a "." key. So we fake it so people can more seemlessly
+ // is "," the numeric keypad has a "." key. So we fake it so people can more seamlessly
// enter numbers using the keypad
if(KNumber::decimalSeparator() != QLatin1String(".")) {
if(e->key() == Qt::Key_Period && e->modifiers() & Qt::KeypadModifier) {
pbPeriod->animateClick();
}
}
if (((e->modifiers() & Qt::NoModifier) == 0) || (e->modifiers() & Qt::ShiftModifier)) {
switch (e->key()) {
case Qt::Key_Backspace:
calc_display->deleteLastDigit();
break;
}
}
if (e->key() == Qt::Key_Control) {
emit switchShowAccels(true);
}
}
//------------------------------------------------------------------------------
// Name: keyReleaseEvent
// Desc: handles keyrelease events
//------------------------------------------------------------------------------
void KCalculator::keyReleaseEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Control) {
emit switchShowAccels(false);
}
}
//------------------------------------------------------------------------------
// Name: slotAngleSelected
// Desc: changes the selected angle system
//------------------------------------------------------------------------------
void KCalculator::slotAngleSelected(int mode) {
angle_mode_ = mode;
statusBar()->setAngleMode(KCalcStatusBar::AngleMode(mode));
switch (mode) {
case DegMode:
calc_display->setStatusText(AngleField, QLatin1String("Deg"));
break;
case RadMode:
calc_display->setStatusText(AngleField, QLatin1String("Rad"));
break;
case GradMode:
calc_display->setStatusText(AngleField, QLatin1String("Gra"));
break;
default: // we shouldn't ever end up here
angle_mode_ = RadMode;
}
KCalcSettings::setAngleMode(angle_mode_);
}
//------------------------------------------------------------------------------
// Name: slotEEclicked
-// Desc: starts the entering of numers using scientific notation
+// Desc: starts the entering of numbers using scientific notation
//------------------------------------------------------------------------------
void KCalculator::slotEEclicked() {
calc_display->newCharacter(QLatin1Char('e'));
}
//------------------------------------------------------------------------------
// Name: slotShifttoggled
// Desc: updates the shift state for alternate button functionality
//------------------------------------------------------------------------------
void KCalculator::slotShifttoggled(bool flag) {
shift_mode_ = flag;
emit switchMode(ModeShift, flag);
statusBar()->setShiftIndicator(shift_mode_);
if (shift_mode_) {
calc_display->setStatusText(ShiftField, i18n("Shift"));
} else {
calc_display->setStatusText(ShiftField, QString());
}
}
//------------------------------------------------------------------------------
// Name: slotHyptoggled
// Desc: updates the Hyp state for alternate trig button functionality
//------------------------------------------------------------------------------
void KCalculator::slotHyptoggled(bool flag) {
- // toggle between hyperbolic and standart trig functions
+ // toggle between hyperbolic and standard trig functions
hyp_mode_ = flag;
emit switchMode(ModeHyperbolic, flag);
}
//------------------------------------------------------------------------------
// Name: slotMemRecallclicked
// Desc: recalls a value from memory
//------------------------------------------------------------------------------
void KCalculator::slotMemRecallclicked() {
// temp. work-around
calc_display->sendEvent(KCalcDisplay::EventReset);
calc_display->setAmount(memory_num_);
updateDisplay({});
}
//------------------------------------------------------------------------------
// Name: slotMemStoreclicked
// Desc: stores a value into memory
//------------------------------------------------------------------------------
void KCalculator::slotMemStoreclicked() {
EnterEqual();
memory_num_ = calc_display->getAmount();
calc_display->setStatusText(MemField, QLatin1String("M"));
statusBar()->setMemoryIndicator(true);
pbMemRecall->setEnabled(true);
}
//------------------------------------------------------------------------------
// Name: slotNumberclicked
// Desc: user has entered a digit
//------------------------------------------------------------------------------
void KCalculator::slotNumberclicked(int number_clicked) {
calc_display->enterDigit(number_clicked);
core.setOnlyUpdateOperation(false);
}
//------------------------------------------------------------------------------
// Name: slotSinclicked
// Desc: executes the sine function
//------------------------------------------------------------------------------
void KCalculator::slotSinclicked() {
if (hyp_mode_) {
// sinh or arsinh
if (!shift_mode_) {
core.SinHyp(calc_display->getAmount());
} else {
core.AreaSinHyp(calc_display->getAmount());
}
} else {
// sine or arcsine
if (!shift_mode_) {
switch (angle_mode_) {
case DegMode:
core.SinDeg(calc_display->getAmount());
break;
case RadMode:
core.SinRad(calc_display->getAmount());
break;
case GradMode:
core.SinGrad(calc_display->getAmount());
break;
}
} else {
switch (angle_mode_) {
case DegMode:
core.ArcSinDeg(calc_display->getAmount());
break;
case RadMode:
core.ArcSinRad(calc_display->getAmount());
break;
case GradMode:
core.ArcSinGrad(calc_display->getAmount());
break;
}
}
}
updateDisplay(UPDATE_FROM_CORE);
}
//------------------------------------------------------------------------------
// Name: slotPlusMinusclicked
// Desc: changes sign of number being displayed
//------------------------------------------------------------------------------
void KCalculator::slotPlusMinusclicked() {
// display can only change sign, when in input mode, otherwise we
// need the core to do this.
if (!calc_display->sendEvent(KCalcDisplay::EventChangeSign)) {
core.InvertSign(calc_display->getAmount());
updateDisplay(UPDATE_FROM_CORE);
}
}
//------------------------------------------------------------------------------
// Name: slotMemPlusMinusclicked
// Desc: handles arithmetic on values stored in memory
//------------------------------------------------------------------------------
void KCalculator::slotMemPlusMinusclicked() {
bool tmp_shift_mode = shift_mode_; // store this, because next command deletes shift_mode_
EnterEqual(); // finish calculation so far, to store result into MEM
if (!tmp_shift_mode) {
memory_num_ += calc_display->getAmount();
} else {
memory_num_ -= calc_display->getAmount();
}
pbShift->setChecked(false);
statusBar()->setMemoryIndicator(true);
calc_display->setStatusText(MemField, i18n("M"));
pbMemRecall->setEnabled(true);
}
//------------------------------------------------------------------------------
// Name: slotSinclicked
// Desc: executes the cosine function
//------------------------------------------------------------------------------
void KCalculator::slotCosclicked() {
if (hyp_mode_) {
// cosh or arcosh
if (!shift_mode_) {
core.CosHyp(calc_display->getAmount());
} else {
core.AreaCosHyp(calc_display->getAmount());
}
} else {
// cosine or arccosine
if (!shift_mode_) {
switch (angle_mode_) {
case DegMode:
core.CosDeg(calc_display->getAmount());
break;
case RadMode:
core.CosRad(calc_display->getAmount());
break;
case GradMode:
core.CosGrad(calc_display->getAmount());
break;
}
} else {
switch (angle_mode_) {
case DegMode:
core.ArcCosDeg(calc_display->getAmount());
break;
case RadMode:
core.ArcCosRad(calc_display->getAmount());
break;
case GradMode:
core.ArcCosGrad(calc_display->getAmount());
break;
}
}
}
updateDisplay(UPDATE_FROM_CORE);
}
//------------------------------------------------------------------------------
// Name: slotSinclicked
// Desc: executes the recipricol function
//------------------------------------------------------------------------------
void KCalculator::slotReciclicked() {
if (shift_mode_) {
core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_BINOM);
} else {
core.Reciprocal(calc_display->getAmount());
updateDisplay(UPDATE_FROM_CORE);
return;
}
// temp. work-around
KNumber tmp_num = calc_display->getAmount();
calc_display->sendEvent(KCalcDisplay::EventReset);
calc_display->setAmount(tmp_num);
updateDisplay({});
}
//------------------------------------------------------------------------------
// Name: slotSinclicked
// Desc: executes the tangent function
//------------------------------------------------------------------------------
void KCalculator::slotTanclicked() {
if (hyp_mode_) {
// tanh or artanh
if (!shift_mode_) {
core.TangensHyp(calc_display->getAmount());
} else {
core.AreaTangensHyp(calc_display->getAmount());
}
} else {
// tan or arctan
if (!shift_mode_) {
switch (angle_mode_) {
case DegMode:
core.TangensDeg(calc_display->getAmount());
break;
case RadMode:
core.TangensRad(calc_display->getAmount());
break;
case GradMode:
core.TangensGrad(calc_display->getAmount());
break;
}
} else {
switch (angle_mode_) {
case DegMode:
core.ArcTangensDeg(calc_display->getAmount());
break;
case RadMode:
core.ArcTangensRad(calc_display->getAmount());
break;
case GradMode:
core.ArcTangensGrad(calc_display->getAmount());
break;
}
}
}
updateDisplay(UPDATE_FROM_CORE);
}
//------------------------------------------------------------------------------
// Name: slotFactorialclicked
// Desc: executes the factorial function
//------------------------------------------------------------------------------
void KCalculator::slotFactorialclicked() {
// Set WaitCursor, as this operation may take looooong
// time and UI frezes with large numbers. User needs some
// visual feedback.
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
if (!shift_mode_) {
core.Factorial(calc_display->getAmount());
} else {
core.Gamma(calc_display->getAmount());
}
QApplication::restoreOverrideCursor();
updateDisplay(UPDATE_FROM_CORE);
}
//------------------------------------------------------------------------------
// Name: slotLogclicked
// Desc: executes the Log function
//------------------------------------------------------------------------------
void KCalculator::slotLogclicked() {
if (!shift_mode_) {
core.Log10(calc_display->getAmount());
} else {
core.Exp10(calc_display->getAmount());
}
updateDisplay(UPDATE_FROM_CORE);
}
//------------------------------------------------------------------------------
// Name: slotSquareclicked
// Desc: executes the x^2 function
//------------------------------------------------------------------------------
void KCalculator::slotSquareclicked() {
if (!shift_mode_) {
core.Square(calc_display->getAmount());
} else {
core.SquareRoot(calc_display->getAmount());
}
updateDisplay(UPDATE_FROM_CORE);
}
//------------------------------------------------------------------------------
// Name: slotCubeclicked
// Desc: executes the x^3 function
//------------------------------------------------------------------------------
void KCalculator::slotCubeclicked() {
if (!shift_mode_) {
core.Cube(calc_display->getAmount());
} else {
core.CubeRoot(calc_display->getAmount());
}
updateDisplay(UPDATE_FROM_CORE);
}
//------------------------------------------------------------------------------
// Name: slotCubeclicked
// Desc: executes the ln function
//------------------------------------------------------------------------------
void KCalculator::slotLnclicked() {
if (!shift_mode_) {
core.Ln(calc_display->getAmount());
} else {
core.Exp(calc_display->getAmount());
}
updateDisplay(UPDATE_FROM_CORE);
}
//------------------------------------------------------------------------------
// Name: slotPowerclicked
// Desc: executes the x^y function
//------------------------------------------------------------------------------
void KCalculator::slotPowerclicked() {
if (shift_mode_) {
core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_PWR_ROOT);
pbShift->setChecked(false);
} else {
core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_POWER);
}
// temp. work-around
KNumber tmp_num = calc_display->getAmount();
calc_display->sendEvent(KCalcDisplay::EventReset);
calc_display->setAmount(tmp_num);
updateDisplay({});
}
//------------------------------------------------------------------------------
// Name: slotMemClearclicked
// Desc: executes the MC function
//------------------------------------------------------------------------------
void KCalculator::slotMemClearclicked() {
memory_num_ = KNumber::Zero;
statusBar()->setMemoryIndicator(false);
calc_display->setStatusText(MemField, QString());
pbMemRecall->setDisabled(true);
}
//------------------------------------------------------------------------------
// Name: slotBackspaceclicked
// Desc: removes the last input digit
//------------------------------------------------------------------------------
void KCalculator::slotBackspaceclicked() {
calc_display->deleteLastDigit();
}
//------------------------------------------------------------------------------
// Name: slotClearclicked
// Desc: clears the display
//------------------------------------------------------------------------------
void KCalculator::slotClearclicked() {
calc_display->sendEvent(KCalcDisplay::EventClear);
}
//------------------------------------------------------------------------------
// Name: slotAllClearclicked
// Desc: clears everything
//------------------------------------------------------------------------------
void KCalculator::slotAllClearclicked() {
core.Reset();
calc_display->sendEvent(KCalcDisplay::EventReset);
updateDisplay(UPDATE_FROM_CORE);
}
//------------------------------------------------------------------------------
// Name: slotParenOpenclicked
// Desc: starts a sub-expression
//------------------------------------------------------------------------------
void KCalculator::slotParenOpenclicked() {
core.ParenOpen(calc_display->getAmount());
}
//------------------------------------------------------------------------------
// Name: slotParenCloseclicked
// Desc: ends a sub-expression
//------------------------------------------------------------------------------
void KCalculator::slotParenCloseclicked() {
core.ParenClose(calc_display->getAmount());
updateDisplay(UPDATE_FROM_CORE);
}
//------------------------------------------------------------------------------
// Name: slotANDclicked
// Desc: executes a bitwise AND
//------------------------------------------------------------------------------
void KCalculator::slotANDclicked() {
core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_AND);
updateDisplay(UPDATE_FROM_CORE);
}
//------------------------------------------------------------------------------
// Name: slotMultiplicationclicked
// Desc: executes multiplication
//------------------------------------------------------------------------------
void KCalculator::slotMultiplicationclicked() {
core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_MULTIPLY);
updateDisplay(UPDATE_FROM_CORE);
}
//------------------------------------------------------------------------------
// Name: slotDivisionclicked
// Desc: executes division
//------------------------------------------------------------------------------
void KCalculator::slotDivisionclicked() {
core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_DIVIDE);
updateDisplay(UPDATE_FROM_CORE);
}
//------------------------------------------------------------------------------
// Name: slotORclicked
// Desc: executes a bitwise OR
//------------------------------------------------------------------------------
void KCalculator::slotORclicked() {
core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_OR);
updateDisplay(UPDATE_FROM_CORE);
}
//------------------------------------------------------------------------------
// Name: slotXORclicked
// Desc: executes a bitwise XOR
//------------------------------------------------------------------------------
void KCalculator::slotXORclicked() {
core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_XOR);
updateDisplay(UPDATE_FROM_CORE);
}
//------------------------------------------------------------------------------
// Name: slotPlusclicked
// Desc: executes addition
//------------------------------------------------------------------------------
void KCalculator::slotPlusclicked() {
core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_ADD);
updateDisplay(UPDATE_FROM_CORE);
}
//------------------------------------------------------------------------------
// Name: slotPlusclicked
// Desc: executes subtraction
//------------------------------------------------------------------------------
void KCalculator::slotMinusclicked() {
core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_SUBTRACT);
updateDisplay(UPDATE_FROM_CORE);
}
//------------------------------------------------------------------------------
// Name: slotLeftShiftclicked
// Desc: executes a bitwise left shift
//------------------------------------------------------------------------------
void KCalculator::slotLeftShiftclicked() {
core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_LSH);
updateDisplay(UPDATE_FROM_CORE);
}
//------------------------------------------------------------------------------
// Name: slotLeftShiftclicked
// Desc: executes a bitwise right shift
//------------------------------------------------------------------------------
void KCalculator::slotRightShiftclicked() {
core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_RSH);
updateDisplay(UPDATE_FROM_CORE);
}
//------------------------------------------------------------------------------
// Name: slotPeriodclicked
// Desc: enters a decimal into the input stream
//------------------------------------------------------------------------------
void KCalculator::slotPeriodclicked() {
// i know this isn't locale friendly, should be converted to appropriate
// value at lower levels
calc_display->newCharacter(QLocale().decimalPoint());
}
//------------------------------------------------------------------------------
// Name: EnterEqual
// Desc: calculates and displays the result of the pending operations
//------------------------------------------------------------------------------
void KCalculator::EnterEqual() {
core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_EQUAL);
updateDisplay(UPDATE_FROM_CORE | UPDATE_STORE_RESULT);
}
//------------------------------------------------------------------------------
// Name: slotEqualclicked
// Desc: calculates and displays the result of the pending operations
//------------------------------------------------------------------------------
void KCalculator::slotEqualclicked() {
EnterEqual();
}
//------------------------------------------------------------------------------
// Name: slotPercentclicked
// Desc: calculates and displays the result of the pending operations as a percent
//------------------------------------------------------------------------------
void KCalculator::slotPercentclicked() {
core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_PERCENT);
updateDisplay(UPDATE_FROM_CORE);
}
//------------------------------------------------------------------------------
// Name: slotNegateclicked
// Desc: executes a bitwise 2's compliment
// NOTE: implicitly converts the value to an unsigned quantity
//------------------------------------------------------------------------------
void KCalculator::slotNegateclicked() {
core.Complement(calc_display->getAmount());
updateDisplay(UPDATE_FROM_CORE);
}
//------------------------------------------------------------------------------
// Name: slotModclicked
// Desc: executes modulous (remainder division)
//------------------------------------------------------------------------------
void KCalculator::slotModclicked(){
if (shift_mode_) {
core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_INTDIV);
} else {
core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_MOD);
}
updateDisplay(UPDATE_FROM_CORE);
}
//------------------------------------------------------------------------------
// Name: slotStatNumclicked
// Desc: executes Sum function
//------------------------------------------------------------------------------
void KCalculator::slotStatNumclicked() {
if (!shift_mode_) {
core.StatCount(KNumber::Zero);
} else {
pbShift->setChecked(false);
core.StatSum(KNumber::Zero);
}
updateDisplay(UPDATE_FROM_CORE);
}
//------------------------------------------------------------------------------
// Name: slotStatMeanclicked
// Desc: executes Mean function
//------------------------------------------------------------------------------
void KCalculator::slotStatMeanclicked() {
if (!shift_mode_) {
core.StatMean(KNumber::Zero);
} else {
pbShift->setChecked(false);
core.StatSumSquares(KNumber::Zero);
}
updateDisplay(UPDATE_FROM_CORE);
}
//------------------------------------------------------------------------------
// Name: slotStatStdDevclicked
// Desc: executes STD function
//------------------------------------------------------------------------------
void KCalculator::slotStatStdDevclicked() {
if (shift_mode_) {
// std (n-1)
core.StatStdDeviation(KNumber::Zero);
pbShift->setChecked(false);
} else {
// std (n)
core.StatStdSample(KNumber::Zero);
}
updateDisplay(UPDATE_FROM_CORE);
}
//------------------------------------------------------------------------------
// Name: slotStatMedianclicked
// Desc: executes Median function
//------------------------------------------------------------------------------
void KCalculator::slotStatMedianclicked() {
if (!shift_mode_) {
// std (n-1)
core.StatMedian(KNumber::Zero);
} else {
// std (n)
core.StatMedian(KNumber::Zero);
pbShift->setChecked(false);
}
// TODO: it seems two different modes should be implemented, but...?
updateDisplay(UPDATE_FROM_CORE);
}
//------------------------------------------------------------------------------
// Name: slotStatDataInputclicked
// Desc: enters a value for statistical functions
//------------------------------------------------------------------------------
void KCalculator::slotStatDataInputclicked() {
if (!shift_mode_) {
core.StatDataNew(calc_display->getAmount());
} else {
pbShift->setChecked(false);
core.StatDataDel(KNumber::Zero);
statusBar()->showMessage(i18n("Last stat item erased"), 3000);
}
updateDisplay(UPDATE_FROM_CORE);
}
//------------------------------------------------------------------------------
// Name: slotStatClearDataclicked
// Desc: clears memory for statical functions
//------------------------------------------------------------------------------
void KCalculator::slotStatClearDataclicked() {
if (!shift_mode_) {
core.StatClearAll(KNumber::Zero);
statusBar()->showMessage(i18n("Stat mem cleared"), 3000);
} else {
pbShift->setChecked(false);
updateDisplay({});
}
}
//------------------------------------------------------------------------------
// Name: slotConstclicked
// Desc: enters a constant
//------------------------------------------------------------------------------
void KCalculator::slotConstclicked(int button) {
if(KCalcConstButton *btn = qobject_cast(const_buttons_[button])) {
if (!shift_mode_) {
// set the display to the configured value of constant button
// internally, we deal with C locale style numbers, we need to convert
QString val = btn->constant();
val.replace(QLatin1Char('.'), KNumber::decimalSeparator());
calc_display->setAmount(KNumber(val));
} else {
pbShift->setChecked(false);
// internally, we deal with C locale style numbers, we need to convert
QString val = calc_display->text();
val.replace(KNumber::decimalSeparator(), QLatin1String("."));
KCalcSettings::setValueConstant(button, val);
// below set new tooltip
btn->setLabelAndTooltip();
// work around: after storing a number, pressing a digit should start
// a new number
calc_display->setAmount(calc_display->getAmount());
}
updateDisplay({});
}
}
//------------------------------------------------------------------------------
// Name: showSettings
// Desc: opens the shows the settings dialog
//------------------------------------------------------------------------------
void KCalculator::showSettings() {
// Check if there is already a dialog and if so bring
// it to the foreground.
if (KConfigDialog::showDialog(QLatin1String("settings"))) {
return;
}
// Create a new dialog with the same name as the above checking code.
KConfigDialog *const dialog = new KConfigDialog(this, QLatin1String("settings"), KCalcSettings::self());
// general settings
General *const general = new General(nullptr);
general->kcfg_Precision->setMaximum(maxprecision);
dialog->addPage(general, i18n("General"), QLatin1String("accessories-calculator"), i18n("General Settings"));
// font settings
Fonts *const fonts = new Fonts(nullptr);
dialog->addPage(fonts, i18n("Font"), QLatin1String("preferences-desktop-font"), i18n("Select Display Font"));
// color settings
Colors *const color = new Colors(nullptr);
dialog->addPage(color, i18n("Colors"), QLatin1String("format-fill-color"), i18n("Button & Display Colors"));
// constant settings
if (!constants_) {
constants_ = new Constants(nullptr);
}
KCalcConstMenu *tmp_menu;
tmp_menu = new KCalcConstMenu(this);
connect(tmp_menu, &KCalcConstMenu::triggeredConstant, this, &KCalculator::slotChooseScientificConst0);
constants_->pushButton0->setMenu(tmp_menu);
tmp_menu = new KCalcConstMenu(this);
connect(tmp_menu, &KCalcConstMenu::triggeredConstant, this, &KCalculator::slotChooseScientificConst1);
constants_->pushButton1->setMenu(tmp_menu);
tmp_menu = new KCalcConstMenu(this);
connect(tmp_menu, &KCalcConstMenu::triggeredConstant, this, &KCalculator::slotChooseScientificConst2);
constants_->pushButton2->setMenu(tmp_menu);
tmp_menu = new KCalcConstMenu(this);
connect(tmp_menu, &KCalcConstMenu::triggeredConstant, this, &KCalculator::slotChooseScientificConst3);
constants_->pushButton3->setMenu(tmp_menu);
tmp_menu = new KCalcConstMenu(this);
connect(tmp_menu, &KCalcConstMenu::triggeredConstant, this, &KCalculator::slotChooseScientificConst4);
constants_->pushButton4->setMenu(tmp_menu);
tmp_menu = new KCalcConstMenu(this);
connect(tmp_menu, &KCalcConstMenu::triggeredConstant, this, &KCalculator::slotChooseScientificConst5);
constants_->pushButton5->setMenu(tmp_menu);
dialog->addPage(constants_, i18n("Constants"), QLatin1String("preferences-kcalc-constants"), i18n("Define Constants"));
// When the user clicks OK or Apply we want to update our settings.
connect(dialog, &KConfigDialog::settingsChanged, this, &KCalculator::updateSettings);
// Display the dialog.
dialog->show();
}
// these 6 slots are just a quick hack, instead of setting the
// TextEdit fields in the configuration dialog, we are setting the
// Settingvalues themselves!!
//------------------------------------------------------------------------------
// Name: slotChooseScientificConst0
// Desc: updates constants value
//------------------------------------------------------------------------------
void KCalculator::slotChooseScientificConst0(const science_constant &chosen_const) {
constants_->kcfg_valueConstant0->setText(chosen_const.value);
constants_->kcfg_nameConstant0->setText(chosen_const.label);
}
//------------------------------------------------------------------------------
// Name: slotChooseScientificConst1
// Desc: updates constants value
//------------------------------------------------------------------------------
void KCalculator::slotChooseScientificConst1(const science_constant &chosen_const) {
constants_->kcfg_valueConstant1->setText(chosen_const.value);
constants_->kcfg_nameConstant1->setText(chosen_const.label);
}
//------------------------------------------------------------------------------
// Name: slotChooseScientificConst2
// Desc: updates constants value
//------------------------------------------------------------------------------
void KCalculator::slotChooseScientificConst2(const science_constant &chosen_const) {
constants_->kcfg_valueConstant2->setText(chosen_const.value);
constants_->kcfg_nameConstant2->setText(chosen_const.label);
}
//------------------------------------------------------------------------------
// Name: slotChooseScientificConst3
// Desc: updates constants value
//------------------------------------------------------------------------------
void KCalculator::slotChooseScientificConst3(const science_constant &chosen_const) {
constants_->kcfg_valueConstant3->setText(chosen_const.value);
constants_->kcfg_nameConstant3->setText(chosen_const.label);
}
//------------------------------------------------------------------------------
// Name: slotChooseScientificConst4
// Desc: updates constants value
//------------------------------------------------------------------------------
void KCalculator::slotChooseScientificConst4(const science_constant &chosen_const) {
constants_->kcfg_valueConstant4->setText(chosen_const.value);
constants_->kcfg_nameConstant4->setText(chosen_const.label);
}
//------------------------------------------------------------------------------
// Name: slotChooseScientificConst5
// Desc: updates constants value
//------------------------------------------------------------------------------
void KCalculator::slotChooseScientificConst5(const science_constant &chosen_const) {
constants_->kcfg_valueConstant5->setText(chosen_const.value);
constants_->kcfg_nameConstant5->setText(chosen_const.label);
}
//------------------------------------------------------------------------------
// Name: slotSetSimpleMode
// Desc: sets the calculator to have a simple layout
//------------------------------------------------------------------------------
void KCalculator::slotSetSimpleMode() {
action_constants_show_->setChecked(false);
action_constants_show_->setEnabled(false);
action_bitset_show_->setEnabled(false);
showMemButtons(false);
showScienceButtons(false);
showStatButtons(false);
showLogicButtons(false);
// hide some individual buttons, which are not in one of the above groups
pbShift->hide();
pbMod->hide();
pbReci->hide();
pbFactorial->hide();
pbSquare->hide();
pbPower->hide();
pbCube->hide();
pbBackspace->hide();
pbEE->hide();
// delete the constant menu since it doesn't fit
delete constants_menu_;
constants_menu_ = nullptr;
KCalcSettings::setCalculatorMode(KCalcSettings::EnumCalculatorMode::simple);
// must be done after setting the calculator mode because the
// slotBitsetshow slot should save the state only in numeral mode
action_bitset_show_->setChecked(false);
}
//------------------------------------------------------------------------------
// Name: slotSetScienceMode
// Desc: sets the calculator to science mode
//------------------------------------------------------------------------------
void KCalculator::slotSetScienceMode() {
action_constants_show_->setEnabled(true);
action_constants_show_->setChecked(KCalcSettings::showConstants());
action_bitset_show_->setEnabled(false);
// show some individual buttons
pbShift->show();
pbMod->show();
pbReci->show();
pbFactorial->show();
pbSquare->show();
pbPower->show();
pbCube->show();
pbBackspace->show();
pbEE->show();
// show or hide some groups of buttons
showMemButtons(true);
showScienceButtons(true);
showStatButtons(false);
showLogicButtons(false);
if(!constants_menu_) {
constants_menu_ = createConstantsMenu();
menuBar()->insertMenu((menuBar()->actions)()[2], constants_menu_);
}
KCalcSettings::setCalculatorMode(KCalcSettings::EnumCalculatorMode::science);
// must be done after setting the calculator mode because the
// slotBitsetshow slot should save the state only in numeral mode
action_bitset_show_->setChecked(false);
}
//------------------------------------------------------------------------------
// Name: slotSetStatisticMode
// Desc: sets the calculator to stats mode
//------------------------------------------------------------------------------
void KCalculator::slotSetStatisticMode() {
action_constants_show_->setEnabled(true);
action_constants_show_->setChecked(KCalcSettings::showConstants());
action_bitset_show_->setEnabled(false);
// show some individual buttons
pbShift->show();
pbMod->show();
pbReci->show();
pbFactorial->show();
pbSquare->show();
pbPower->show();
pbCube->show();
pbBackspace->show();
pbEE->show();
// show or hide some groups of buttons
showMemButtons(true);
showScienceButtons(true);
showStatButtons(true);
showLogicButtons(false);
if(!constants_menu_) {
constants_menu_ = createConstantsMenu();
menuBar()->insertMenu((menuBar()->actions)()[2], constants_menu_);
}
KCalcSettings::setCalculatorMode(KCalcSettings::EnumCalculatorMode::statistics);
// must be done after setting the calculator mode because the
// slotBitsetshow slot should save the state only in numeral mode
action_bitset_show_->setChecked(false);
}
//------------------------------------------------------------------------------
// Name: slotSetNumeralMode
// Desc: sets the calculator to numerical ("programmers") mode
//------------------------------------------------------------------------------
void KCalculator::slotSetNumeralMode() {
action_constants_show_->setChecked(false);
action_constants_show_->setEnabled(false);
action_bitset_show_->setEnabled(true);
action_bitset_show_->setChecked(KCalcSettings::showBitset());
// show some individual buttons
pbShift->show();
pbMod->show();
pbReci->show();
pbFactorial->show();
pbSquare->show();
pbPower->show();
pbCube->show();
pbBackspace->show();
pbEE->show();
// show or hide some groups of buttons
showMemButtons(true);
showScienceButtons(false);
showStatButtons(false);
showLogicButtons(true);
if(!constants_menu_) {
constants_menu_ = createConstantsMenu();
menuBar()->insertMenu((menuBar()->actions)()[2], constants_menu_);
}
KCalcSettings::setCalculatorMode(KCalcSettings::EnumCalculatorMode::numeral);
}
//------------------------------------------------------------------------------
// Name: showMemButtons
// Desc: hides or shows the memory buttons
//------------------------------------------------------------------------------
void KCalculator::showMemButtons(bool toggled) {
if (toggled) {
foreach(QAbstractButton *btn, mem_button_list_) {
btn->show();
}
} else {
foreach(QAbstractButton *btn, mem_button_list_) {
btn->hide();
}
// these are in the mem_button_list_ but should not be hidden
pbClear->show();
pbAllClear->show();
}
}
//------------------------------------------------------------------------------
// Name: showStatButtons
// Desc: hides or shows the stat buttons
//------------------------------------------------------------------------------
void KCalculator::showStatButtons(bool toggled) {
if (toggled) {
foreach(QAbstractButton *btn, stat_buttons_) {
btn->show();
}
} else {
foreach(QAbstractButton *btn, stat_buttons_) {
btn->hide();
}
}
}
//------------------------------------------------------------------------------
// Name: showScienceButtons
// Desc: hides or shows the science buttons
//------------------------------------------------------------------------------
void KCalculator::showScienceButtons(bool toggled) {
if (toggled) {
foreach(QAbstractButton* btn, scientific_buttons_) {
btn->show();
}
foreach(QAbstractButton* btn, angle_choose_group_->buttons()) {
btn->show();
}
setAngle();
statusBar()->setAngleModeIndicatorVisible(true);
} else {
foreach(QAbstractButton* btn, scientific_buttons_) {
btn->hide();
}
foreach(QAbstractButton* btn, angle_choose_group_->buttons()) {
btn->hide();
}
statusBar()->setAngleModeIndicatorVisible(false);
calc_display->setStatusText(AngleField, QString());
}
}
//------------------------------------------------------------------------------
// Name: showLogicButtons
// Desc: hides or shows the logic buttons
//------------------------------------------------------------------------------
void KCalculator::showLogicButtons(bool toggled) {
if (toggled) {
mBitset->setEnabled(true);
connect(mBitset, &KCalcBitset::valueChanged, this, &KCalculator::slotBitsetChanged);
connect(calc_display, &KCalcDisplay::changedAmount, this, &KCalculator::slotUpdateBitset);
foreach(QAbstractButton* btn, logic_buttons_) {
btn->show();
}
setBase();
statusBar()->setBaseIndicatorVisible(true);
foreach(QAbstractButton *btn, base_choose_group_->buttons()) {
btn->show();
}
for (int i = 10; i < 16; ++i) {
(num_button_group_->button(i))->show();
}
} else {
mBitset->setEnabled(false);
disconnect(mBitset, &KCalcBitset::valueChanged, this, &KCalculator::slotBitsetChanged);
disconnect(calc_display, &KCalcDisplay::changedAmount, this, &KCalculator::slotUpdateBitset);
foreach(QAbstractButton* btn, logic_buttons_) {
btn->hide();
}
// Hide Hex-Buttons, but first switch back to decimal
decRadio->animateClick(0);
foreach(QAbstractButton *btn, base_choose_group_->buttons()) {
btn->hide();
}
statusBar()->setBaseIndicatorVisible(false);
calc_display->setStatusText(BaseField, QString());
for (int i = 10; i < 16; ++i) {
(num_button_group_->button(i))->hide();
}
}
}
//------------------------------------------------------------------------------
// Name: slotConstantsShow
// Desc: hides or shows the constants buttons
//------------------------------------------------------------------------------
void KCalculator::slotConstantsShow(bool toggled) {
if (toggled) {
foreach(QAbstractButton *btn, const_buttons_) {
btn->show();
}
} else {
foreach(QAbstractButton *btn, const_buttons_) {
btn->hide();
}
}
KCalcSettings::setShowConstants(toggled);
}
//------------------------------------------------------------------------------
// Name: slotBitsetshow
// Desc: hides or shows the bitset buttons
//------------------------------------------------------------------------------
void KCalculator::slotBitsetshow(bool toggled) {
mBitset->setVisible(toggled);
if (KCalcSettings::calculatorMode() == KCalcSettings::EnumCalculatorMode::numeral) {
KCalcSettings::setShowBitset(toggled);
}
}
//------------------------------------------------------------------------------
// Name: slotBitsetshow
// Desc: This function is for setting the constant names configured in the
// kcalc settings menu. If the user doesn't enter a name for the
// constant C1 to C6 is used.
//------------------------------------------------------------------------------
void KCalculator::changeButtonNames() {
foreach(QAbstractButton *btn, const_buttons_) {
if (KCalcConstButton *const constbtn = qobject_cast(btn)) {
constbtn->setLabelAndTooltip();
}
}
}
//------------------------------------------------------------------------------
// Name: slotBitsetChanged
// Desc: updates the bitset display
// NOTE: sets display to *unsigned* value
//------------------------------------------------------------------------------
void KCalculator::slotBitsetChanged(quint64 value) {
calc_display->setAmount(KNumber(value));
updateDisplay({});
}
//------------------------------------------------------------------------------
// Name: slotUpdateBitset
// Desc: updates the bitset itself
//------------------------------------------------------------------------------
void KCalculator::slotUpdateBitset(const KNumber &nr) {
mBitset->setValue(nr.toUint64());
}
//------------------------------------------------------------------------------
// Name: updateSettings
// Desc: updates the persistent settings
//------------------------------------------------------------------------------
void KCalculator::updateSettings() {
changeButtonNames();
setColors();
setFonts();
setPrecision();
// Show the result in the app's caption in taskbar (wishlist - bug #52858)
disconnect(calc_display, SIGNAL(changedText(QString)), this, nullptr);
if (KCalcSettings::captionResult()) {
connect(calc_display, &KCalcDisplay::changedText, this, &KCalculator::setWindowTitle);
} else {
setCaption(QString());
}
calc_display->changeSettings();
updateGeometry();
}
//------------------------------------------------------------------------------
// Name: updateDisplay
// Desc: updates the display
//------------------------------------------------------------------------------
void KCalculator::updateDisplay(UpdateFlags flags) {
if(flags & UPDATE_FROM_CORE) {
calc_display->updateFromCore(core, (flags & UPDATE_STORE_RESULT) != 0);
core.setOnlyUpdateOperation(true);
} else {
calc_display->update();
}
pbShift->setChecked(false);
}
//------------------------------------------------------------------------------
// Name: setColors
// Desc: set the various colours
//------------------------------------------------------------------------------
void KCalculator::setColors() {
calc_display->changeSettings();
KColorScheme schemeButtons(QPalette::Active, KColorScheme::Button);
const QColor defaultColor = schemeButtons.background().color();
if (KCalcSettings::numberButtonsColor() == defaultColor
&& KCalcSettings::functionButtonsColor() == defaultColor
&& KCalcSettings::statButtonsColor() == defaultColor
&& KCalcSettings::hexButtonsColor() == defaultColor
&& KCalcSettings::memoryButtonsColor() == defaultColor
&& KCalcSettings::operationButtonsColor() == defaultColor) {
return;
}
const QString sheet = QLatin1String("QPushButton { background-color: %1 }");
const QColor numPal(KCalcSettings::numberButtonsColor());
for (int i = 0; i < 10; ++i) {
(num_button_group_->button(i))->setStyleSheet(sheet.arg(numPal.name()));
}
const QColor funcPal(KCalcSettings::functionButtonsColor());
foreach(QAbstractButton *btn, function_button_list_) {
btn->setStyleSheet(sheet.arg(funcPal.name()));
}
const QColor statPal(KCalcSettings::statButtonsColor());
foreach(QAbstractButton *btn, stat_buttons_) {
btn->setStyleSheet(sheet.arg(statPal.name()));
}
const QColor hexPal(KCalcSettings::hexButtonsColor());
for (int i = 10; i < 16; ++i) {
(num_button_group_->button(i))->setStyleSheet(sheet.arg(hexPal.name()));
}
const QColor memPal(KCalcSettings::memoryButtonsColor());
foreach(QAbstractButton *btn, mem_button_list_) {
btn->setStyleSheet(sheet.arg(memPal.name()));
}
const QColor opPal(KCalcSettings::operationButtonsColor());
foreach(QAbstractButton *btn, operation_button_list_) {
btn->setStyleSheet(sheet.arg(opPal.name()));
}
}
//------------------------------------------------------------------------------
// Name: setFonts
// Desc: set the various fonts
//------------------------------------------------------------------------------
void KCalculator::setFonts() {
foreach(QObject *obj, leftPad->children()) {
if (KCalcButton *const button = qobject_cast(obj)) {
button->setFont(KCalcSettings::buttonFont());
}
}
foreach(QObject *obj, numericPad->children()) {
if (KCalcButton *const button = qobject_cast(obj)) {
button->setFont(KCalcSettings::buttonFont());
}
}
foreach(QObject *obj, rightPad->children()) {
if (KCalcButton *const button = qobject_cast(obj)) {
button->setFont(KCalcSettings::buttonFont());
}
}
updateGeometry();
}
//------------------------------------------------------------------------------
// Name: event
// Desc: catch application's palette and font change events
//------------------------------------------------------------------------------
bool KCalculator::event(QEvent *e) {
switch (e->type()) {
case QEvent::ApplicationFontChange:
setFonts();
break;
case QEvent::ApplicationPaletteChange:
setColors();
break;
default:
break;
}
return KXmlGuiWindow::event(e);
}
//------------------------------------------------------------------------------
// Name: setPrecision
// Desc: set the precision of the display
//------------------------------------------------------------------------------
void KCalculator::setPrecision() {
KNumber::setDefaultFloatPrecision(KCalcSettings::precision());
updateDisplay({});
}
//------------------------------------------------------------------------------
// Name: setAngle
// Desc: sets the angle mode
//------------------------------------------------------------------------------
void KCalculator::setAngle() {
if (QAbstractButton *const btn = angle_choose_group_->button(KCalcSettings::angleMode())) {
btn->animateClick(0);
}
}
//------------------------------------------------------------------------------
// Name: setBase
// Desc: sets the numeric base
//------------------------------------------------------------------------------
void KCalculator::setBase() {
if (QAbstractButton *const btn = base_choose_group_->button(KCalcSettings::baseMode())) {
btn->animateClick(0);
}
}
//------------------------------------------------------------------------------
// Name: eventFilter
// Desc: general event filter used to track events like drag/drop
//------------------------------------------------------------------------------
bool KCalculator::eventFilter(QObject *o, QEvent *e) {
switch (e->type()) {
case QEvent::DragEnter: {
QDragEnterEvent *const ev = reinterpret_cast(e);
ev->setAccepted(KColorMimeData::canDecode(ev->mimeData()));
return true;
}
case QEvent::DragLeave: {
return true;
}
case QEvent::Drop: {
KCalcButton *const calcButton = qobject_cast(o);
if (!calcButton) {
return false;
}
QDropEvent *const ev = reinterpret_cast(e);
QColor c = KColorMimeData::fromMimeData(ev->mimeData());
if (c.isValid()) {
QString cn = c.name();
QString sheet = QLatin1String("background-color: %1");
QList *list;
const int num_but = num_button_group_->buttons().indexOf(calcButton);
if (num_but != -1) {
// Was it hex-button or normal digit??
if (num_but < 10) {
for (int i = 0; i < 10; ++i) {
(num_button_group_->buttons()[i])->setStyleSheet(sheet.arg(cn));
}
} else {
for (int i = 10; i < 16; ++i) {
(num_button_group_->buttons()[i])->setStyleSheet(sheet.arg(cn));
}
}
return true;
} else if (function_button_list_.contains(calcButton)) {
list = &function_button_list_;
} else if (stat_button_list_.contains(calcButton)) {
list = &stat_button_list_;
} else if (mem_button_list_.contains(calcButton)) {
list = &mem_button_list_;
} else if (operation_button_list_.contains(calcButton)) {
list = &operation_button_list_;
} else {
return false;
}
for (int i = 0; i < list->size(); ++i) {
list->at(i)->setStyleSheet(sheet.arg(cn));
}
}
return true;
}
// FALL THROUGH
default:
return KXmlGuiWindow::eventFilter(o, e);
}
}
////////////////////////////////////////////////////////////////
// Include the meta-object code for classes in this file
//
//------------------------------------------------------------------------------
// Name: kdemain
// Desc: entry point of the application
//------------------------------------------------------------------------------
extern "C" Q_DECL_EXPORT int kdemain(int argc, char *argv[]) {
QApplication app(argc, argv);
KLocalizedString::setApplicationDomain("kcalc");
/**
* enable high dpi support
*/
app.setAttribute(Qt::AA_UseHighDpiPixmaps, true);
Kdelibs4ConfigMigrator migrate(QLatin1String("kcalc"));
migrate.setConfigFiles(QStringList() << QLatin1String("kcalcrc"));
migrate.setUiFiles(QStringList() << QLatin1String("kcalcui.rc"));
migrate.migrate();
KAboutData aboutData(QStringLiteral("kcalc"),
i18n("KCalc"),
QStringLiteral(KCALC_VERSION_STRING),
i18n(description),
KAboutLicense::GPL,
i18n("Copyright © 2008-2013, Evan Teran\n"
"Copyright © 2000-2008, The KDE Team\n"
"Copyright © 2003-2005, Klaus Niederkr" "\xc3\xbc" "ger\n"
"Copyright © 1996-2000, Bernd Johannes Wuebben"),
QStringLiteral(),
QStringLiteral("http://utils.kde.org/projects/kcalc"));
// Klaus Niederkrueger
aboutData.addAuthor(i18n("Klaus Niederkr" "\xc3\xbc" "ger"), QString(), QStringLiteral("kniederk@math.uni-koeln.de"));
aboutData.addAuthor(i18n("Bernd Johannes Wuebben"), QString(), QStringLiteral("wuebben@kde.org"));
aboutData.addAuthor(i18n("Evan Teran"), i18n("Maintainer"), QStringLiteral("eteran@alum.rit.edu"));
aboutData.addAuthor(i18n("Espen Sand"), QString(), QStringLiteral("espen@kde.org"));
aboutData.addAuthor(i18n("Chris Howells"), QString(), QStringLiteral("howells@kde.org"));
aboutData.addAuthor(i18n("Aaron J. Seigo"), QString(), QStringLiteral("aseigo@olympusproject.org"));
aboutData.addAuthor(i18n("Charles Samuels"), QString(), QStringLiteral("charles@altair.dhs.org"));
// Rene Merou
aboutData.addAuthor(i18n("Ren" "\xc3\xa9" " M" "\xc3\xa9" "rou"), QString(), QStringLiteral("ochominutosdearco@yahoo.es"));
aboutData.addAuthor(i18n("Michel Marti"), QString(), QStringLiteral("mma@objectxp.com"));
aboutData.addAuthor(i18n("David Johnson"), QString(), QStringLiteral("david@usermode.org"));
KAboutData::setApplicationData(aboutData);
app.setWindowIcon(QIcon::fromTheme(QLatin1String("accessories-calculator"), app.windowIcon()));
QCommandLineParser parser;
parser.addHelpOption();
parser.addVersionOption();
aboutData.setupCommandLine(&parser);
parser.process(app);
aboutData.processCommandLine(&parser);
// force system locale to "C" internally [bug 159168]
setlocale(LC_NUMERIC, "C");
KNumber::setGroupSeparator(QLocale().groupSeparator());
KNumber::setDecimalSeparator(QString(QLocale().decimalPoint()));
KCalculator *calc = new KCalculator(nullptr);
calc->show();
return app.exec();
}
diff --git a/knumber/knumber.cpp b/knumber/knumber.cpp
index 872e5db..d9d7a36 100644
--- a/knumber/knumber.cpp
+++ b/knumber/knumber.cpp
@@ -1,946 +1,946 @@
/*
Copyright (C) 2001 - 2013 Evan Teran
evan.teran@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include
#include "knumber.h"
#include "knumber_base.h"
#include "knumber_error.h"
#include "knumber_float.h"
#include "knumber_fraction.h"
#include "knumber_integer.h"
#include
#include
#include
#include
QString KNumber::GroupSeparator = QLatin1String(",");
QString KNumber::DecimalSeparator = QLatin1String(".");
const KNumber KNumber::Zero(QLatin1String("0"));
const KNumber KNumber::One(QLatin1String("1"));
const KNumber KNumber::NegOne(QLatin1String("-1"));
const KNumber KNumber::PosInfinity(QLatin1String("inf"));
const KNumber KNumber::NegInfinity(QLatin1String("-inf"));
const KNumber KNumber::NaN(QLatin1String("nan"));
namespace {
namespace impl {
//------------------------------------------------------------------------------
// Name: increment
//------------------------------------------------------------------------------
void increment(QString &str, int position) {
for (int i = position; i >= 0; i--) {
const char last_char = str[i].toLatin1();
switch (last_char) {
case '0':
str[i] = QLatin1Char('1');
break;
case '1':
str[i] = QLatin1Char('2');
break;
case '2':
str[i] = QLatin1Char('3');
break;
case '3':
str[i] = QLatin1Char('4');
break;
case '4':
str[i] = QLatin1Char('5');
break;
case '5':
str[i] = QLatin1Char('6');
break;
case '6':
str[i] = QLatin1Char('7');
break;
case '7':
str[i] = QLatin1Char('8');
break;
case '8':
str[i] = QLatin1Char('9');
break;
case '9':
str[i] = QLatin1Char('0');
if (i == 0) {
str.prepend(QLatin1Char('1'));
}
continue;
case '.':
continue;
}
break;
}
}
//------------------------------------------------------------------------------
// Name: round
//------------------------------------------------------------------------------
void round(QString &str, int precision) {
// Cut off if more digits in fractional part than 'precision'
int decimalSymbolPos = str.indexOf(QLatin1Char('.'));
if (decimalSymbolPos == -1) {
if (precision == 0) {
return;
} else if (precision > 0) { // add dot if missing (and needed)
str.append(QLatin1Char('.'));
decimalSymbolPos = str.length() - 1;
}
}
// fill up with more than enough zeroes (in case fractional part too short)
str.append(QString().fill(QLatin1Char('0'), precision));
// Now decide whether to round up or down
const char last_char = str[decimalSymbolPos + precision + 1].toLatin1();
switch (last_char) {
case '0':
case '1':
case '2':
case '3':
case '4':
// nothing to do, rounding down
break;
case '5':
case '6':
case '7':
case '8':
case '9':
// rounding up
increment(str, decimalSymbolPos + precision);
break;
default:
break;
}
decimalSymbolPos = str.indexOf(QLatin1Char('.'));
str.truncate(decimalSymbolPos + precision + 1);
// if precision == 0 delete also '.'
if (precision == 0) {
str = str.section(QLatin1Char('.'), 0, 0);
}
}
}
//------------------------------------------------------------------------------
// Name: round
//------------------------------------------------------------------------------
QString round(const QString &s, int precision) {
QString tmp = s;
if (precision < 0 || !QRegExp(QLatin1String("^[+-]?\\d+(\\.\\d+)*(e[+-]?\\d+)?$")).exactMatch(tmp)) {
return s;
}
// Skip the sign (for now)
const bool neg = (tmp[0] == QLatin1Char('-'));
if (neg || tmp[0] == QLatin1Char('+')) {
tmp.remove(0, 1);
}
// Split off exponential part (including 'e'-symbol)
QString mantString = tmp.section(QLatin1Char('e'), 0, 0, QString::SectionCaseInsensitiveSeps);
QString expString = tmp.section(QLatin1Char('e'), 1, 1, QString::SectionCaseInsensitiveSeps | QString::SectionIncludeLeadingSep);
if (expString.length() == 1) {
expString.clear();
}
impl::round(mantString, precision);
if (neg) {
mantString.prepend(QLatin1Char('-'));
}
return mantString + expString;
}
}
//------------------------------------------------------------------------------
// Name: setGroupSeparator
//------------------------------------------------------------------------------
void KNumber::setGroupSeparator(const QString &ch) {
GroupSeparator = ch;
}
//------------------------------------------------------------------------------
// Name: setDecimalSeparator
//------------------------------------------------------------------------------
void KNumber::setDecimalSeparator(const QString &ch) {
DecimalSeparator = ch;
}
//------------------------------------------------------------------------------
// Name: groupSeparator
//------------------------------------------------------------------------------
QString KNumber::groupSeparator() {
return GroupSeparator;
}
//------------------------------------------------------------------------------
// Name: decimalSeparator
//------------------------------------------------------------------------------
QString KNumber::decimalSeparator() {
return DecimalSeparator;
}
//------------------------------------------------------------------------------
// Name: setDefaultFloatPrecision
//------------------------------------------------------------------------------
void KNumber::setDefaultFloatPrecision(int precision) {
// Need to transform decimal digits into binary digits
const unsigned long int bin_prec = static_cast(double(precision) * M_LN10 / M_LN2 + 1);
mpf_set_default_prec(bin_prec);
}
//------------------------------------------------------------------------------
// Name: setSplitoffIntegerForFractionOutput
//------------------------------------------------------------------------------
void KNumber::setSplitoffIntegerForFractionOutput(bool x) {
detail::knumber_fraction::set_split_off_integer_for_fraction_output(x);
}
//------------------------------------------------------------------------------
// Name: setDefaultFractionalInput
//------------------------------------------------------------------------------
void KNumber::setDefaultFractionalInput(bool x) {
detail::knumber_fraction::set_default_fractional_input(x);
}
//------------------------------------------------------------------------------
// Name: setDefaultFloatOutput
//------------------------------------------------------------------------------
void KNumber::setDefaultFloatOutput(bool x) {
detail::knumber_fraction::set_default_fractional_output(!x);
}
//------------------------------------------------------------------------------
// Name: Pi
//------------------------------------------------------------------------------
KNumber KNumber::Pi() {
// TODO: after 4.10 release:
// create a new constructor which works just like the normal QString
// accepting constructor, but allows us to specify separator
// characters, this will allow things to be done slightly more
// efficiently
QString s(QLatin1String("3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068"));
s.replace(QLatin1Char('.'), DecimalSeparator);
return KNumber(s);
}
//------------------------------------------------------------------------------
// Name: Euler
//------------------------------------------------------------------------------
KNumber KNumber::Euler() {
// TODO: after 4.10 release:
// create a new constructor which works just like the normal QString
// accepting constructor, but allows us to specify separator
// characters, this will allow things to be done slightly more
// efficiently
QString s(QLatin1String("2.7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274"));
s.replace(QLatin1Char('.'), DecimalSeparator);
return KNumber(s);
}
//------------------------------------------------------------------------------
// Name: KNumber
//------------------------------------------------------------------------------
KNumber::KNumber() : value_(new detail::knumber_integer(0)) {
}
//------------------------------------------------------------------------------
// Name: KNumber
//------------------------------------------------------------------------------
KNumber::KNumber(const QString &s) : value_(nullptr) {
const QRegExp special_regex(QLatin1String("^(inf|-inf|nan)$"));
const QRegExp integer_regex(QLatin1String("^[+-]?\\d+$"));
const QRegExp fraction_regex(QLatin1String("^[+-]?\\d+/\\d+$"));
const QRegExp float_regex(QString(QLatin1String("^([+-]?\\d*)(%1\\d*)?(e([+-]?\\d+))?$")).arg(QRegExp::escape(DecimalSeparator)));
if (special_regex.exactMatch(s)) {
value_ = new detail::knumber_error(s);
} else if (integer_regex.exactMatch(s)) {
value_ = new detail::knumber_integer(s);
} else if (fraction_regex.exactMatch(s)) {
value_ = new detail::knumber_fraction(s);
simplify();
} else if (float_regex.exactMatch(s)) {
if(detail::knumber_fraction::default_fractional_input) {
const QStringList list = float_regex.capturedTexts();
if(list.size() == 5) {
const QString ipart = list[1];
const QString fpart = list[2];
const QString epart = list[3];
const int e_val = list[4].toInt();
QString num = ipart + fpart.mid(1);
QString den = QLatin1String("1") + QString(fpart.size() - 1, QLatin1Char('0'));
if(e_val < 0) {
den = den + QString(::abs(e_val), QLatin1Char('0'));
} else if(e_val > 0) {
num = num + QString(::abs(e_val), QLatin1Char('0'));
}
value_ = new detail::knumber_fraction(QString(QLatin1String("%1/%2")).arg(num, den));
simplify();
return;
}
}
- // we need to normalize the decimal searator to US style because that's
+ // we need to normalize the decimal separator to US style because that's
// the only type that the GMP function accept
QString new_s = s;
new_s.replace(DecimalSeparator, QLatin1String("."));
value_ = new detail::knumber_float(new_s);
simplify();
} else {
value_ = new detail::knumber_error(detail::knumber_error::ERROR_UNDEFINED);
}
}
//------------------------------------------------------------------------------
// Name: KNumber
//------------------------------------------------------------------------------
KNumber::KNumber(qint32 value) : value_(new detail::knumber_integer(value)) {
}
//------------------------------------------------------------------------------
// Name: KNumber
//------------------------------------------------------------------------------
KNumber::KNumber(qint64 value) : value_(new detail::knumber_integer(value)) {
}
//------------------------------------------------------------------------------
// Name: KNumber
//------------------------------------------------------------------------------
KNumber::KNumber(quint32 value) : value_(new detail::knumber_integer(value)) {
}
//------------------------------------------------------------------------------
// Name: KNumber
//------------------------------------------------------------------------------
KNumber::KNumber(quint64 value) : value_(new detail::knumber_integer(value)) {
}
//------------------------------------------------------------------------------
// Name: KNumber
//------------------------------------------------------------------------------
KNumber::KNumber(qint64 num, quint64 den) : value_(new detail::knumber_fraction(num, den)) {
}
//------------------------------------------------------------------------------
// Name: KNumber
//------------------------------------------------------------------------------
KNumber::KNumber(quint64 num, quint64 den) : value_(new detail::knumber_fraction(num, den)) {
}
#ifdef HAVE_LONG_DOUBLE
//------------------------------------------------------------------------------
// Name: KNumber
//------------------------------------------------------------------------------
KNumber::KNumber(long double value) : value_(new detail::knumber_float(value)) {
simplify();
}
#endif
//------------------------------------------------------------------------------
// Name: KNumber
//------------------------------------------------------------------------------
KNumber::KNumber(double value) : value_(new detail::knumber_float(value)) {
simplify();
}
//------------------------------------------------------------------------------
// Name: KNumber
//------------------------------------------------------------------------------
KNumber::KNumber(const KNumber &other) : value_(nullptr) {
if(&other != this) {
value_ = other.value_->clone();
}
}
//------------------------------------------------------------------------------
// Name: ~KNumber
//------------------------------------------------------------------------------
KNumber::~KNumber() {
delete value_;
}
//------------------------------------------------------------------------------
// Name: type
//------------------------------------------------------------------------------
KNumber::Type KNumber::type() const {
if(dynamic_cast(value_)) {
return TYPE_INTEGER;
} else if(dynamic_cast(value_)) {
return TYPE_FLOAT;
} else if(dynamic_cast(value_)) {
return TYPE_FRACTION;
} else if(dynamic_cast(value_)) {
return TYPE_ERROR;
} else {
Q_ASSERT(0);
return TYPE_ERROR;
}
}
//------------------------------------------------------------------------------
// Name: operator=
//------------------------------------------------------------------------------
KNumber &KNumber::operator=(const KNumber &rhs) {
KNumber(rhs).swap(*this);
return *this;
}
//------------------------------------------------------------------------------
// Name: swap
//------------------------------------------------------------------------------
void KNumber::swap(KNumber &other) {
qSwap(value_, other.value_);
}
//------------------------------------------------------------------------------
// Name: integerPart
//------------------------------------------------------------------------------
KNumber KNumber::integerPart() const {
KNumber x(*this);
if(detail::knumber_integer *const p = dynamic_cast(value_)) {
// NO-OP
Q_UNUSED(p);
} else if(detail::knumber_float *const p = dynamic_cast(value_)) {
detail::knumber_base *v = new detail::knumber_integer(p);
qSwap(v, x.value_);
delete v;
} else if(detail::knumber_fraction *const p = dynamic_cast(value_)) {
detail::knumber_base *v = new detail::knumber_integer(p);
qSwap(v, x.value_);
delete v;
} else if(detail::knumber_error *const p = dynamic_cast(value_)) {
// NO-OP
Q_UNUSED(p);
} else {
Q_ASSERT(0);
}
return x;
}
//------------------------------------------------------------------------------
// Name: simplify
//------------------------------------------------------------------------------
void KNumber::simplify() {
if(value_->is_integer()) {
if(detail::knumber_integer *const p = dynamic_cast(value_)) {
// NO-OP
Q_UNUSED(p);
} else if(detail::knumber_float *const p = dynamic_cast(value_)) {
detail::knumber_base *v = new detail::knumber_integer(p);
qSwap(v, value_);
delete v;
} else if(detail::knumber_fraction *const p = dynamic_cast(value_)) {
detail::knumber_base *v = new detail::knumber_integer(p);
qSwap(v, value_);
delete v;
} else if(detail::knumber_error *const p = dynamic_cast(value_)) {
// NO-OP
Q_UNUSED(p);
} else {
Q_ASSERT(0);
}
}
}
//------------------------------------------------------------------------------
// Name: operator+=
//------------------------------------------------------------------------------
KNumber &KNumber::operator+=(const KNumber &rhs) {
value_ = value_->add(rhs.value_);
simplify();
return *this;
}
//------------------------------------------------------------------------------
// Name: operator-=
//------------------------------------------------------------------------------
KNumber &KNumber::operator-=(const KNumber &rhs) {
value_ = value_->sub(rhs.value_);
simplify();
return *this;
}
//------------------------------------------------------------------------------
// Name: operator*=
//------------------------------------------------------------------------------
KNumber &KNumber::operator*=(const KNumber &rhs) {
value_ = value_->mul(rhs.value_);
simplify();
return *this;
}
//------------------------------------------------------------------------------
// Name: operator/=
//------------------------------------------------------------------------------
KNumber &KNumber::operator/=(const KNumber &rhs) {
// Fix for bug #330577, x /0 is undefined, not infinity
// Also indirectly fixes bug #329897, tan(90) is undefined, not infinity
if(rhs == Zero) {
*this = NaN;
return *this;
}
value_ = value_->div(rhs.value_);
simplify();
return *this;
}
//------------------------------------------------------------------------------
// Name: operator%=
//------------------------------------------------------------------------------
KNumber &KNumber::operator%=(const KNumber &rhs) {
value_ = value_->mod(rhs.value_);
simplify();
return *this;
}
//------------------------------------------------------------------------------
// Name: operator&=
//------------------------------------------------------------------------------
KNumber &KNumber::operator&=(const KNumber &rhs) {
value_ = value_->bitwise_and(rhs.value_);
return *this;
}
//------------------------------------------------------------------------------
// Name: operator|=
//------------------------------------------------------------------------------
KNumber &KNumber::operator|=(const KNumber &rhs) {
value_ = value_->bitwise_or(rhs.value_);
return *this;
}
//------------------------------------------------------------------------------
// Name: operator^=
//------------------------------------------------------------------------------
KNumber &KNumber::operator^=(const KNumber &rhs) {
value_ = value_->bitwise_xor(rhs.value_);
return *this;
}
//------------------------------------------------------------------------------
// Name: operator<<
//------------------------------------------------------------------------------
KNumber &KNumber::operator<<=(const KNumber &rhs) {
value_ = value_->bitwise_shift(rhs.value_);
return *this;
}
//------------------------------------------------------------------------------
// Name: operator>>=
//------------------------------------------------------------------------------
KNumber &KNumber::operator>>=(const KNumber &rhs) {
const KNumber rhs_neg(-rhs);
value_ = value_->bitwise_shift(rhs_neg.value_);
return *this;
}
//------------------------------------------------------------------------------
// Name: operator-
//------------------------------------------------------------------------------
KNumber KNumber::operator-() const {
KNumber x(*this);
x.value_ = x.value_->neg();
return x;
}
//------------------------------------------------------------------------------
// Name: operator~
//------------------------------------------------------------------------------
KNumber KNumber::operator~() const {
KNumber x(*this);
x.value_ = x.value_->cmp();
return x;
}
//------------------------------------------------------------------------------
// Name: toQString
//------------------------------------------------------------------------------
QString KNumber::toQString(int width, int precision) const {
if(value_->is_zero()) {
return QLatin1String("0");
}
QString s;
if(detail::knumber_integer *const p = dynamic_cast(value_)) {
if(width > 0) {
s = detail::knumber_float(p).toString(width);
} else {
s = value_->toString(width);
}
} else if(detail::knumber_float *const p = dynamic_cast(value_)) {
if(width > 0) {
s = value_->toString(width);
} else {
s = value_->toString(3 * mpf_get_default_prec() / 10);
}
} else if(detail::knumber_fraction *const p = dynamic_cast(value_)) {
s = value_->toString(width);
} else {
return value_->toString(width);
}
// now do some rounding to make sure things are displayed reasonably
if (precision >= 0) {
return round(s, precision);
} else {
return s;
}
}
//------------------------------------------------------------------------------
// Name: toUint64
//------------------------------------------------------------------------------
quint64 KNumber::toUint64() const {
return value_->toUint64();
}
//------------------------------------------------------------------------------
// Name: toInt64
//------------------------------------------------------------------------------
qint64 KNumber::toInt64() const {
return value_->toInt64();
}
//------------------------------------------------------------------------------
// Name: abs
//------------------------------------------------------------------------------
KNumber KNumber::abs() const {
KNumber z(*this);
z.value_ = z.value_->abs();
z.simplify();
return z;
}
//------------------------------------------------------------------------------
// Name: cbrt
//------------------------------------------------------------------------------
KNumber KNumber::cbrt() const {
KNumber z(*this);
z.value_ = z.value_->cbrt();
z.simplify();
return z;
}
//------------------------------------------------------------------------------
// Name: sqrt
//------------------------------------------------------------------------------
KNumber KNumber::sqrt() const {
KNumber z(*this);
z.value_ = z.value_->sqrt();
z.simplify();
return z;
}
//------------------------------------------------------------------------------
// Name: pow
//------------------------------------------------------------------------------
KNumber KNumber::pow(const KNumber &x) const {
// Fix for bug #330711 (pow(0, -x) was causing crashes
// Fix for bug #330597 (pow(0,0) was 1 now it is NaN
// Thanks to Raushan Kumar for identifying the issue and submitting
// patches
if(*this == Zero && x <= Zero) {
return NaN;
}
// if the LHS is a special then we can use this function
// no matter what, cause the result is a special too
if(!dynamic_cast(value_)) {
// number much bigger than this tend to crash GMP with
// an abort
if(x > KNumber(QLatin1String("1000000000"))) {
return PosInfinity;
}
}
KNumber z(*this);
z.value_ = z.value_->pow(x.value_);
z.simplify();
return z;
}
//------------------------------------------------------------------------------
// Name: sin
//------------------------------------------------------------------------------
KNumber KNumber::sin() const {
KNumber z(*this);
z.value_ = z.value_->sin();
z.simplify();
return z;
}
//------------------------------------------------------------------------------
// Name: cos
//------------------------------------------------------------------------------
KNumber KNumber::cos() const {
KNumber z(*this);
z.value_ = z.value_->cos();
z.simplify();
return z;
}
//------------------------------------------------------------------------------
// Name: tan
//------------------------------------------------------------------------------
KNumber KNumber::tan() const {
KNumber z(*this);
z.value_ = z.value_->tan();
z.simplify();
return z;
}
//------------------------------------------------------------------------------
// Name: tgamma
//------------------------------------------------------------------------------
KNumber KNumber::tgamma() const {
KNumber z(*this);
if(z > KNumber(QLatin1String("10000000000"))) {
return PosInfinity;
}
z.value_ = z.value_->tgamma();
z.simplify();
return z;
}
//------------------------------------------------------------------------------
// Name: asin
//------------------------------------------------------------------------------
KNumber KNumber::asin() const {
KNumber z(*this);
z.value_ = z.value_->asin();
z.simplify();
return z;
}
//------------------------------------------------------------------------------
// Name: acos
//------------------------------------------------------------------------------
KNumber KNumber::acos() const {
KNumber z(*this);
z.value_ = z.value_->acos();
z.simplify();
return z;
}
//------------------------------------------------------------------------------
// Name: atan
//------------------------------------------------------------------------------
KNumber KNumber::atan() const {
KNumber z(*this);
z.value_ = z.value_->atan();
z.simplify();
return z;
}
//------------------------------------------------------------------------------
// Name: sinh
//------------------------------------------------------------------------------
KNumber KNumber::sinh() const {
KNumber z(*this);
z.value_ = z.value_->sinh();
z.simplify();
return z;
}
//------------------------------------------------------------------------------
// Name: cosh
//------------------------------------------------------------------------------
KNumber KNumber::cosh() const {
KNumber z(*this);
z.value_ = z.value_->cosh();
z.simplify();
return z;
}
//------------------------------------------------------------------------------
// Name: tanh
//------------------------------------------------------------------------------
KNumber KNumber::tanh() const {
KNumber z(*this);
z.value_ = z.value_->tanh();
z.simplify();
return z;
}
//------------------------------------------------------------------------------
// Name: asinh
//------------------------------------------------------------------------------
KNumber KNumber::asinh() const {
KNumber z(*this);
z.value_ = z.value_->asinh();
z.simplify();
return z;
}
//------------------------------------------------------------------------------
// Name: acosh
//------------------------------------------------------------------------------
KNumber KNumber::acosh() const {
KNumber z(*this);
z.value_ = z.value_->acosh();
z.simplify();
return z;
}
//------------------------------------------------------------------------------
// Name: atanh
//------------------------------------------------------------------------------
KNumber KNumber::atanh() const {
KNumber z(*this);
z.value_ = z.value_->atanh();
z.simplify();
return z;
}
//------------------------------------------------------------------------------
// Name: factorial
//------------------------------------------------------------------------------
KNumber KNumber::factorial() const {
KNumber z(*this);
// number much bigger than this tend to crash GMP with
// an abort
if(z > KNumber(QLatin1String("10000000000"))) {
return PosInfinity;
}
z.value_ = z.value_->factorial();
z.simplify();
return z;
}
//------------------------------------------------------------------------------
// Name: log2
//------------------------------------------------------------------------------
KNumber KNumber::log2() const {
KNumber z(*this);
z.value_ = z.value_->log2();
z.simplify();
return z;
}
//------------------------------------------------------------------------------
// Name: log10
//------------------------------------------------------------------------------
KNumber KNumber::log10() const {
KNumber z(*this);
z.value_ = z.value_->log10();
z.simplify();
return z;
}
//------------------------------------------------------------------------------
// Name: ln
//------------------------------------------------------------------------------
KNumber KNumber::ln() const {
KNumber z(*this);
z.value_ = z.value_->ln();
z.simplify();
return z;
}
//------------------------------------------------------------------------------
// Name: floor
//------------------------------------------------------------------------------
KNumber KNumber::floor() const {
KNumber z(*this);
z.value_ = z.value_->floor();
z.simplify();
return z;
}
//------------------------------------------------------------------------------
// Name: ceil
//------------------------------------------------------------------------------
KNumber KNumber::ceil() const {
KNumber z(*this);
z.value_ = z.value_->ceil();
z.simplify();
return z;
}
//------------------------------------------------------------------------------
// Name: exp2
//------------------------------------------------------------------------------
KNumber KNumber::exp2() const {
KNumber z(*this);
z.value_ = z.value_->exp2();
z.simplify();
return z;
}
//------------------------------------------------------------------------------
// Name: exp10
//------------------------------------------------------------------------------
KNumber KNumber::exp10() const {
KNumber z(*this);
z.value_ = z.value_->exp10();
z.simplify();
return z;
}
//------------------------------------------------------------------------------
// Name: exp
//------------------------------------------------------------------------------
KNumber KNumber::exp() const {
KNumber z(*this);
z.value_ = z.value_->exp();
z.simplify();
return z;
}
//------------------------------------------------------------------------------
// Name: bin
//------------------------------------------------------------------------------
KNumber KNumber::bin(const KNumber &x) const {
KNumber z(*this);
z.value_ = z.value_->bin(x.value_);
z.simplify();
return z;
}
diff --git a/knumber/knumber_fraction.cpp b/knumber/knumber_fraction.cpp
index 289cc59..d651e6d 100644
--- a/knumber/knumber_fraction.cpp
+++ b/knumber/knumber_fraction.cpp
@@ -1,909 +1,909 @@
/*
Copyright (C) 2001 - 2013 Evan Teran
evan.teran@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include
#include "knumber_integer.h"
#include "knumber_float.h"
#include "knumber_fraction.h"
#include "knumber_error.h"
#include
#include
namespace detail {
bool knumber_fraction::default_fractional_input = false;
bool knumber_fraction::default_fractional_output = true;
bool knumber_fraction::split_off_integer_for_fraction_output = false;
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
void knumber_fraction::set_default_fractional_input(bool value) {
default_fractional_input = value;
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
void knumber_fraction::set_default_fractional_output(bool value) {
default_fractional_output = value;
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
void knumber_fraction::set_split_off_integer_for_fraction_output(bool value) {
split_off_integer_for_fraction_output = value;
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_fraction::knumber_fraction(const QString &s) {
mpq_init(mpq_);
mpq_set_str(mpq_, s.toLatin1().constData(), 10);
mpq_canonicalize(mpq_);
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_fraction::knumber_fraction(qint64 num, quint64 den) {
mpq_init(mpq_);
mpq_set_si(mpq_, num, den);
mpq_canonicalize(mpq_);
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_fraction::knumber_fraction(quint64 num, quint64 den) {
mpq_init(mpq_);
mpq_set_ui(mpq_, num, den);
mpq_canonicalize(mpq_);
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_fraction::knumber_fraction(mpq_t mpq) {
mpq_init(mpq_);
mpq_set(mpq_, mpq);
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_fraction::knumber_fraction(const knumber_fraction *value) {
mpq_init(mpq_);
mpq_set(mpq_, value->mpq_);
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_fraction::knumber_fraction(const knumber_integer *value) {
mpq_init(mpq_);
mpq_set_z(mpq_, value->mpz_);
}
#if 0
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_fraction::knumber_fraction(const knumber_float *value) {
mpq_init(mpq_);
mpq_set_f(mpq_, value->mpf_);
}
#endif
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::clone() {
return new knumber_fraction(this);
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_fraction::~knumber_fraction() {
mpq_clear(mpq_);
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
bool knumber_fraction::is_integer() const {
return (mpz_cmp_ui(mpq_denref(mpq_), 1) == 0);
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::add(knumber_base *rhs) {
if(knumber_integer *const p = dynamic_cast(rhs)) {
knumber_fraction q(p);
mpq_add(mpq_, mpq_, q.mpq_);
return this;
} else if(knumber_float *const p = dynamic_cast(rhs)) {
knumber_float *f = new knumber_float(this);
delete this;
return f->add(p);
} else if(knumber_fraction *const p = dynamic_cast(rhs)) {
mpq_add(mpq_, mpq_, p->mpq_);
return this;
} else if(knumber_error *const p = dynamic_cast(rhs)) {
knumber_error *e = new knumber_error(p);
delete this;
return e;
}
Q_ASSERT(0);
return nullptr;
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::sub(knumber_base *rhs) {
if(knumber_integer *const p = dynamic_cast(rhs)) {
knumber_fraction q(p);
mpq_sub(mpq_, mpq_, q.mpq_);
return this;
} else if(knumber_float *const p = dynamic_cast(rhs)) {
knumber_float *f = new knumber_float(this);
delete this;
return f->sub(p);
} else if(knumber_fraction *const p = dynamic_cast(rhs)) {
mpq_sub(mpq_, mpq_, p->mpq_);
return this;
} else if(knumber_error *const p = dynamic_cast(rhs)) {
knumber_error *e = new knumber_error(p);
delete this;
return e->neg();
}
Q_ASSERT(0);
return nullptr;
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::mul(knumber_base *rhs) {
if(knumber_integer *const p = dynamic_cast(rhs)) {
knumber_fraction q(p);
mpq_mul(mpq_, mpq_, q.mpq_);
return this;
} else if(knumber_float *const p = dynamic_cast(rhs)) {
knumber_float *q = new knumber_float(this);
delete this;
return q->mul(p);
} else if(knumber_fraction *const p = dynamic_cast(rhs)) {
mpq_mul(mpq_, mpq_, p->mpq_);
return this;
} else if(knumber_error *const p = dynamic_cast(rhs)) {
if(is_zero()) {
delete this;
knumber_error *e = new knumber_error(knumber_error::ERROR_UNDEFINED);
return e;
}
if(sign() < 0) {
delete this;
knumber_error *e = new knumber_error(p);
return e->neg();
} else {
delete this;
knumber_error *e = new knumber_error(p);
return e;
}
}
Q_ASSERT(0);
return nullptr;
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::div(knumber_base *rhs) {
if(rhs->is_zero()) {
if(sign() < 0) {
delete this;
return new knumber_error(knumber_error::ERROR_NEG_INFINITY);
} else {
delete this;
return new knumber_error(knumber_error::ERROR_POS_INFINITY);
}
}
if(knumber_integer *const p = dynamic_cast(rhs)) {
knumber_fraction f(p);
return div(&f);
} else if(knumber_float *const p = dynamic_cast(rhs)) {
knumber_float *f = new knumber_float(this);
delete this;
return f->div(p);
} else if(knumber_fraction *const p = dynamic_cast(rhs)) {
mpq_div(mpq_, mpq_, p->mpq_);
return this;
} else if(knumber_error *const p = dynamic_cast(rhs)) {
if(p->sign() > 0) {
delete this;
return new knumber_integer(0);
} else if(p->sign() < 0) {
delete this;
return new knumber_integer(0);
}
knumber_error *e = new knumber_error(p);
delete this;
return e;
}
Q_ASSERT(0);
return nullptr;
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::mod(knumber_base *rhs) {
if(rhs->is_zero()) {
delete this;
return new knumber_error(knumber_error::ERROR_UNDEFINED);
}
// NOTE: we don't support modulus operations with non-integer operands
mpq_set_d(mpq_, 0);
return this;
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::bitwise_and(knumber_base *rhs) {
Q_UNUSED(rhs);
delete this;
// NOTE: we don't support bitwise operations with non-integer operands
return new knumber_integer(0);
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::bitwise_xor(knumber_base *rhs) {
Q_UNUSED(rhs);
delete this;
// NOTE: we don't support bitwise operations with non-integer operands
return new knumber_integer(0);
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::bitwise_or(knumber_base *rhs) {
Q_UNUSED(rhs);
delete this;
// NOTE: we don't support bitwise operations with non-integer operands
return new knumber_integer(0);
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::bitwise_shift(knumber_base *rhs) {
Q_UNUSED(rhs);
delete this;
// NOTE: we don't support bitwise operations with non-integer operands
return new knumber_error(knumber_error::ERROR_UNDEFINED);
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::neg() {
mpq_neg(mpq_, mpq_);
return this;
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::abs() {
mpq_abs(mpq_, mpq_);
return this;
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::cmp() {
delete this;
return new knumber_error(knumber_error::ERROR_UNDEFINED);
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::sqrt() {
if(sign() < 0) {
delete this;
return new knumber_error(knumber_error::ERROR_UNDEFINED);
}
if(mpz_perfect_square_p(mpq_numref(mpq_)) && mpz_perfect_square_p(mpq_denref(mpq_))) {
mpz_t num;
mpz_t den;
mpz_init(num);
mpz_init(den);
mpq_get_num(num, mpq_);
mpq_get_den(den, mpq_);
mpz_sqrt(num, num);
mpz_sqrt(den, den);
mpq_set_num(mpq_, num);
mpq_set_den(mpq_, den);
mpq_canonicalize(mpq_);
mpz_clear(num);
mpz_clear(den);
return this;
} else {
knumber_float *f = new knumber_float(this);
delete this;
return f->sqrt();
}
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::cbrt() {
// TODO: figure out how to properly use mpq_numref/mpq_denref here
mpz_t num;
mpz_t den;
mpz_init(num);
mpz_init(den);
mpq_get_num(num, mpq_);
mpq_get_den(den, mpq_);
if(mpz_root(num, num, 3) && mpz_root(den, den, 3)) {
mpq_set_num(mpq_, num);
mpq_set_den(mpq_, den);
mpq_canonicalize(mpq_);
mpz_clear(num);
mpz_clear(den);
return this;
} else {
mpz_clear(num);
mpz_clear(den);
knumber_float *f = new knumber_float(this);
delete this;
return f->cbrt();
}
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::factorial() {
if(sign() < 0) {
delete this;
return new knumber_error(knumber_error::ERROR_UNDEFINED);
}
knumber_integer *i = new knumber_integer(this);
delete this;
return i->factorial();
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::pow(knumber_base *rhs) {
// TODO: figure out how to properly use mpq_numref/mpq_denref here
if(knumber_integer *const p = dynamic_cast(rhs)) {
mpz_t num;
mpz_t den;
mpz_init(num);
mpz_init(den);
mpq_get_num(num, mpq_);
mpq_get_den(den, mpq_);
mpz_pow_ui(num, num, mpz_get_ui(p->mpz_));
mpz_pow_ui(den, den, mpz_get_ui(p->mpz_));
mpq_set_num(mpq_, num);
mpq_set_den(mpq_, den);
mpq_canonicalize(mpq_);
mpz_clear(num);
mpz_clear(den);
if(p->sign() < 0) {
return reciprocal();
} else {
return this;
}
} else if(knumber_float *const p = dynamic_cast(rhs)) {
Q_UNUSED(p);
knumber_float *f = new knumber_float(this);
delete this;
return f->pow(rhs);
} else if(knumber_fraction *const p = dynamic_cast(rhs)) {
// ok, so if any part of the number is > 1,000,000, then we risk
// the pow function overflowing... so we'll just convert to float to be safe
- // TODO: at some point, we should figure out exactly what the threashold is
+ // TODO: at some point, we should figure out exactly what the threshold is
// and if there is a better way to determine if the pow function will
// overflow.
if(mpz_cmpabs_ui(mpq_numref(mpq_), 1000000) > 0 || mpz_cmpabs_ui(mpq_denref(mpq_), 1000000) > 0 || mpz_cmpabs_ui(mpq_numref(p->mpq_), 1000000) > 0 || mpz_cmpabs_ui(mpq_denref(p->mpq_), 1000000) > 0) {
knumber_float *f = new knumber_float(this);
delete this;
return f->pow(rhs);
}
mpz_t lhs_num;
mpz_t lhs_den;
mpz_t rhs_num;
mpz_t rhs_den;
mpz_init(lhs_num);
mpz_init(lhs_den);
mpz_init(rhs_num);
mpz_init(rhs_den);
mpq_get_num(lhs_num, mpq_);
mpq_get_den(lhs_den, mpq_);
mpq_get_num(rhs_num, p->mpq_);
mpq_get_den(rhs_den, p->mpq_);
mpz_pow_ui(lhs_num, lhs_num, mpz_get_ui(rhs_num));
mpz_pow_ui(lhs_den, lhs_den, mpz_get_ui(rhs_num));
if(mpz_sgn(lhs_num) < 0 && mpz_even_p(rhs_den)) {
mpz_clear(lhs_num);
mpz_clear(lhs_den);
mpz_clear(rhs_num);
mpz_clear(rhs_den);
delete this;
return new knumber_error(knumber_error::ERROR_UNDEFINED);
}
if(mpz_sgn(lhs_den) < 0 && mpz_even_p(rhs_den)) {
mpz_clear(lhs_num);
mpz_clear(lhs_den);
mpz_clear(rhs_num);
mpz_clear(rhs_den);
delete this;
return new knumber_error(knumber_error::ERROR_UNDEFINED);
}
const int n1 = mpz_root(lhs_num, lhs_num, mpz_get_ui(rhs_den));
const int n2 = mpz_root(lhs_den, lhs_den, mpz_get_ui(rhs_den));
if(n1 && n2) {
mpq_set_num(mpq_, lhs_num);
mpq_set_den(mpq_, lhs_den);
mpq_canonicalize(mpq_);
mpz_clear(lhs_num);
mpz_clear(lhs_den);
mpz_clear(rhs_num);
mpz_clear(rhs_den);
if(p->sign() < 0) {
return reciprocal();
} else {
return this;
}
} else {
mpz_clear(lhs_num);
mpz_clear(lhs_den);
mpz_clear(rhs_num);
mpz_clear(rhs_den);
knumber_float *f = new knumber_float(this);
delete this;
return f->pow(rhs);
}
} else if(knumber_error *const p = dynamic_cast(rhs)) {
if(p->sign() > 0) {
knumber_error *e = new knumber_error(knumber_error::ERROR_POS_INFINITY);
delete this;
return e;
} else if(p->sign() < 0) {
knumber_integer *n = new knumber_integer(0);
delete this;
return n;
} else {
knumber_error *e = new knumber_error(knumber_error::ERROR_UNDEFINED);
delete this;
return e;
}
}
Q_ASSERT(0);
return nullptr;
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::sin() {
knumber_float *f = new knumber_float(this);
delete this;
return f->sin();
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::floor() {
knumber_float *f = new knumber_float(this);
delete this;
return f->floor();
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::ceil() {
knumber_float *f = new knumber_float(this);
delete this;
return f->ceil();
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::cos() {
knumber_float *f = new knumber_float(this);
delete this;
return f->cos();
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::tgamma() {
knumber_float *f = new knumber_float(this);
delete this;
return f->tgamma();
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::tan() {
knumber_float *f = new knumber_float(this);
delete this;
return f->tan();
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::asin() {
knumber_float *f = new knumber_float(this);
delete this;
return f->asin();
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::acos() {
knumber_float *f = new knumber_float(this);
delete this;
return f->acos();
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::atan() {
knumber_float *f = new knumber_float(this);
delete this;
return f->atan();
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::sinh() {
knumber_float *f = new knumber_float(this);
delete this;
return f->sinh();
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::cosh() {
knumber_float *f = new knumber_float(this);
delete this;
return f->cosh();
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::tanh() {
knumber_float *f = new knumber_float(this);
delete this;
return f->tanh();
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::asinh() {
knumber_float *f = new knumber_float(this);
delete this;
return f->asinh();
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::acosh() {
knumber_float *f = new knumber_float(this);
delete this;
return f->acosh();
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::atanh() {
knumber_float *f = new knumber_float(this);
delete this;
return f->atanh();
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
int knumber_fraction::compare(knumber_base *rhs) {
if(knumber_integer *const p = dynamic_cast(rhs)) {
knumber_fraction f(p);
return mpq_cmp(mpq_, f.mpq_);
} else if(knumber_float *const p = dynamic_cast(rhs)) {
knumber_float f(this);
return f.compare(p);
} else if(knumber_fraction *const p = dynamic_cast(rhs)) {
return mpq_cmp(mpq_, p->mpq_);
} else if(knumber_error *const p = dynamic_cast(rhs)) {
// NOTE: any number compared to NaN/Inf/-Inf always compares less
// at the moment
return -1;
}
Q_ASSERT(0);
return 0;
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
QString knumber_fraction::toString(int precision) const {
if(knumber_fraction::default_fractional_output) {
// TODO: figure out how to properly use mpq_numref/mpq_denref here
knumber_integer integer_part(this);
if(split_off_integer_for_fraction_output && !integer_part.is_zero()) {
mpz_t num;
mpz_init(num);
mpq_get_num(num, mpq_);
knumber_integer integer_part_1(this);
mpz_mul(integer_part.mpz_, integer_part.mpz_, mpq_denref(mpq_));
mpz_sub(num, num, integer_part.mpz_);
if(mpz_sgn(num) < 0) {
mpz_neg(num, num);
}
const size_t size = gmp_snprintf(nullptr, 0, "%Zd %Zd/%Zd", integer_part_1.mpz_, num, mpq_denref(mpq_)) + 1;
QScopedArrayPointer buf(new char[size]);
gmp_snprintf(&buf[0], size, "%Zd %Zd/%Zd", integer_part_1.mpz_, num, mpq_denref(mpq_));
mpz_clear(num);
return QLatin1String(&buf[0]);
} else {
mpz_t num;
mpz_init(num);
mpq_get_num(num, mpq_);
const size_t size = gmp_snprintf(nullptr, 0, "%Zd/%Zd", num, mpq_denref(mpq_)) + 1;
QScopedArrayPointer buf(new char[size]);
gmp_snprintf(&buf[0], size, "%Zd/%Zd", num, mpq_denref(mpq_));
mpz_clear(num);
return QLatin1String(&buf[0]);
}
} else {
return knumber_float(this).toString(precision);
}
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
bool knumber_fraction::is_zero() const {
return mpq_sgn(mpq_) == 0;
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
int knumber_fraction::sign() const {
return mpq_sgn(mpq_);
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::reciprocal() {
mpq_inv(mpq_, mpq_);
return this;
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_integer *knumber_fraction::numerator() const {
mpz_t num;
mpz_init(num);
mpq_get_num(num, mpq_);
knumber_integer *n = new knumber_integer(num);
mpz_clear(num);
return n;
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_integer *knumber_fraction::denominator() const {
mpz_t den;
mpz_init(den);
mpq_get_den(den, mpq_);
knumber_integer *n = new knumber_integer(den);
mpz_clear(den);
return n;
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::log2() {
knumber_float *f = new knumber_float(this);
delete this;
return f->log2();
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::log10() {
knumber_float *f = new knumber_float(this);
delete this;
return f->log10();
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::ln() {
knumber_float *f = new knumber_float(this);
delete this;
return f->ln();
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::exp2() {
knumber_float *f = new knumber_float(this);
delete this;
return f->exp2();
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::exp10() {
knumber_float *f = new knumber_float(this);
delete this;
return f->exp10();
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::exp() {
knumber_float *f = new knumber_float(this);
delete this;
return f->exp();
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
quint64 knumber_fraction::toUint64() const {
return knumber_integer(this).toUint64();
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
qint64 knumber_fraction::toInt64() const {
return knumber_integer(this).toInt64();
}
//------------------------------------------------------------------------------
// Name:
//------------------------------------------------------------------------------
knumber_base *knumber_fraction::bin(knumber_base *rhs) {
Q_UNUSED(rhs);
delete this;
return new knumber_error(knumber_error::ERROR_UNDEFINED);
}
}
diff --git a/stats.cpp b/stats.cpp
index 9ea76ef..a301163 100644
--- a/stats.cpp
+++ b/stats.cpp
@@ -1,213 +1,213 @@
/*
Copyright (C) 2001 - 2013 Evan Teran
evan.teran@gmail.com
Copyright (C) 1996 - 2000 Bernd Johannes Wuebben
wuebben@kde.org
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include "stats.h"
//------------------------------------------------------------------------------
// Name: KStats
// Desc: constructor
//------------------------------------------------------------------------------
KStats::KStats() : error_flag_(false) {
}
//------------------------------------------------------------------------------
// Name: ~KStats
// Desc: destructor
//------------------------------------------------------------------------------
KStats::~KStats() {
}
//------------------------------------------------------------------------------
// Name: clearAll
// Desc: empties the data set
//------------------------------------------------------------------------------
void KStats::clearAll() {
data_.clear();
}
//------------------------------------------------------------------------------
// Name: enterData
// Desc: adds an item to the data set
//------------------------------------------------------------------------------
void KStats::enterData(const KNumber &data) {
data_.push_back(data);
}
//------------------------------------------------------------------------------
// Name: clearLast
-// Desc: remoaves the last item from the data set
+// Desc: removes the last item from the data set
//------------------------------------------------------------------------------
void KStats::clearLast() {
if(!data_.isEmpty()) {
data_.pop_back();
}
}
//------------------------------------------------------------------------------
// Name: sum
// Desc: calculates the SUM of all values in the data set
//------------------------------------------------------------------------------
KNumber KStats::sum() const {
KNumber result = KNumber::Zero;
Q_FOREACH(const KNumber &x, data_) {
result += x;
}
return result;
}
//------------------------------------------------------------------------------
// Name: median
// Desc: calculates the MEDIAN of all values in the data set
//------------------------------------------------------------------------------
KNumber KStats::median() {
KNumber result = KNumber::Zero;
size_t index;
unsigned int bound = count();
if (bound == 0) {
error_flag_ = true;
return KNumber::Zero;
}
if (bound == 1)
return data_.at(0);
// need to copy data_-list, because sorting afterwards
QVector tmp_data(data_);
qSort(tmp_data);
if (bound & 1) { // odd
index = (bound - 1) / 2 + 1;
result = tmp_data.at(index - 1);
} else { // even
index = bound / 2;
result = ((tmp_data.at(index - 1)) + (tmp_data.at(index))) / KNumber(2);
}
return result;
}
//------------------------------------------------------------------------------
// Name: std_kernel
// Desc: calculates the STD Kernel of all values in the data set
//------------------------------------------------------------------------------
KNumber KStats::std_kernel() {
KNumber result = KNumber::Zero;
const KNumber mean_value = mean();
if(mean_value.type() != KNumber::TYPE_ERROR) {
Q_FOREACH(const KNumber &x, data_) {
result += (x - mean_value) * (x - mean_value);
}
}
return result;
}
//------------------------------------------------------------------------------
// Name: sum_of_squares
// Desc: calculates the SUM of all values in the data set (each squared)
//------------------------------------------------------------------------------
KNumber KStats::sum_of_squares() const {
KNumber result = KNumber::Zero;
Q_FOREACH(const KNumber &x, data_) {
result += (x * x);
}
return result;
}
//------------------------------------------------------------------------------
// Name: mean
// Desc: calculates the MEAN of all values in the data set
//------------------------------------------------------------------------------
KNumber KStats::mean() {
if (data_.isEmpty()) {
error_flag_ = true;
return KNumber::Zero;
}
return (sum() / KNumber(count()));
}
//------------------------------------------------------------------------------
// Name: std
// Desc: calculates the STANDARD DEVIATION of all values in the data set
//------------------------------------------------------------------------------
KNumber KStats::std() {
if (data_.isEmpty()) {
error_flag_ = true;
return KNumber::Zero;
}
return (std_kernel() / KNumber(count())).sqrt();
}
//------------------------------------------------------------------------------
// Name: sample_std
// Desc: calculates the SAMPLE STANDARD DEVIATION of all values in the data set
//------------------------------------------------------------------------------
KNumber KStats::sample_std() {
KNumber result = KNumber::Zero;
if (count() < 2) {
error_flag_ = true;
return KNumber::Zero;
}
result = (std_kernel() / KNumber(count() - 1)).sqrt();
return result;
}
//------------------------------------------------------------------------------
// Name: count
// Desc: returns the amount of values in the data set
//------------------------------------------------------------------------------
int KStats::count() const {
return data_.size();
}
//------------------------------------------------------------------------------
// Name: error
// Desc: returns the error state AND clears it
//------------------------------------------------------------------------------
bool KStats::error() {
bool value = error_flag_;
error_flag_ = false;
return value;
}