diff options
Diffstat (limited to 'kcalc')
48 files changed, 10604 insertions, 0 deletions
diff --git a/kcalc/ChangeLog b/kcalc/ChangeLog new file mode 100644 index 0000000..00abb5b --- /dev/null +++ b/kcalc/ChangeLog @@ -0,0 +1,387 @@ +2005-12-29 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Fixed BUG 116835, BUG 118300, BUG 118909 + +2005-10-?? Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Added arbitrary precision + +2005-04-30 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Fix BUG 100316 + +2005-04-25 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Fix BUG 99817. + +2005-04-20 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Change C-style casts for C++ casts, removed some C-style typedefs + +2005-04-02 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * GUI: added statusflags to display, looks very neat (this was + contributed by Bernd Brandstetter; well done!) + +2005-03-30 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * added a Memory-Store button (contributed by Bernd Brandstetter) + +2005-03-29 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * fix M+/- button to change when inverse is pressed + +2005-03-08 Evan Teran <eteran@alum.rit.edu> + * updated about box to reflect my correct email address. This one is + permanent and will never change again + +2005-02-05 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * fix BUG 98522: M- button did not work at least since KDE-3.2. Shame on me, and thanks to + Bernd Brandstetter for reporting the bug. + +2004-12-21 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * added some more contants and dropped Pi-button since not needed. + Instead new cube and cube root button. + +2004-12-17 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * almost finished feature which allows to choose from list + of scientific constants + +2004-12-17 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * started implementation of a list of scientific constants + +2004-12-06 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * further refactoring of configuration options for const buttons + +2004-12-05 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * understood how kconfigxt handles indexed configuration options + +2004-12-03 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * moving through history is now done via undo/redo + this implements wish BUG 93938 + +2004-11-23 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * improved const buttons + +2004-10-20 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * clean up Const-Buttons. More work still required. + +2004-10-16 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * improve Const-Buttons: set value by using INV-Button instead of config-menu + +2004-09-24 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * fixed BUG 90009: the display does not resize in vertical direction anymore + +2004-09-24 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * fixed small bug: switching off Logic-mode tried to change item in statusbar, + but item did not exist. + +2004-09-11 Klaus Niederkrüger <kniederk@math.uni-koeln.de> * + * fix bug 82433: show a check mark next to the angle mode in popup menu + +2004-09-10 Klaus Niederkrüger <kniederk@math.uni-koeln.de> * + * bundle precedence of operators and function pointers into a single + struct. + +2004-09-08 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * moved angle mode logic into GUI + +2004-09-04 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * reduced the number of entry points into the CalcEngine + Aim: enterOperation the only entry point + +2004-08-2? Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * added some labels and tooltips for inverse mode + +2004-08-2? Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * fix to BUG 74657 + * fix to BUG 78726 + +2004-07-30 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Square root button did not work correctly after pressing CTRL (Bug 86004) + +2004-07-30 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Added Accels for Const-Buttons + +2004-07-29 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Fixed BUG 67984 (thanks to André Wöbbeking) + +2004-07-17 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Fixed BUG 85357 + +2004-06-05 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * It was not possible to paste a hex-number starting with "0x" in hex-mode, because hex-mode + prepended automatically "0x" leading to "0x0x...". + +2004-05-16 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Refactored a bit the kcalc_button code. In particular use Richtext only, when needed (a bit faster, + but a lot still to be done). + +2004-05-04 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Masked "&" for the label of the AND button, when displaying the corresponding accel. + Thanks to Sigrid from Trolltech. + +2004-04-27 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Buttons have now their own modes (like inverse Mode etc.) + This allows moving tooltips and labels into kcalc_button.cpp + instead of having everything in kcalc.cpp. + This needs to be cleaned up and the tooltips and labels should be + revised. + +2004-04-05 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Changed accel for OR-button from "O" to "|" + * More accels are visible, when "Ctrl" is used + * disable some buttons like "Sin", "Cos" etc., when not + in decimal mode + +2004-04-05 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Pasted numbers in Hex-Mode are now always interpreted as + hex-numbers (BUG 65167). + +2004-03-26 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Centered labels on buttons + +2004-03-24 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Press (and hold) CTRL-key to see accels for all + buttons (BUG 69850). + +2004-03-19 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Labels like e.g. "x^y" are drawn with QSimpleRichText + Need to center the labels better!! + * KCalcButton supports now two different labels, one for normal, one + for inverse mode. Switch between the two happens via a signal. + +2004-03-11 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Moved functions that paint e.g. "x^y" to the KCalcButton-class. + +2004-03-01 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Created class KCalcButton, which is now used for all QPushButtons. + This will allow later to change the labels more easily, if INV is + pressed, and mucho more... + +2004-02-25 Thomas Weber + * "x^2" and "x^y"-buttons have now superscripted labels + * pressing "INV"-button changes "x^2"-button to square-root etc. + +2004-02-25 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Changed many accels from "accel()->insert()" to + "button->addAccel()". Fixes BUG 75555. + * deactivate EE-button, when Base != DEC + +2004-02-10 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * First step to fix bug 66397. Changing Basemode via Popupmenu is + too clumsy for most programmers. Maybe backport to KDE 3.2 later, + once it has been tested. GUI does not look nice. + +2004-02-06 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Fixed bug 73437. Pasting empty clipboard made kcalc crash. + +2004-02-04 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Moved more accels from keyPressEvent into accels + +2004-01-27 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Fix paste-function: Pasting e.g. "123 \n" did not work + because of the trailing spaces and returns. + +2004-01-25 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Applied patch from Thomas Weber: Creates buttons C1-C6 + to store constants + +2003-12-06 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Fix problem with several identical labels in statusbar + with the help of newly added statusbar->hasItem. + +2003-12-06 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Make Percent work the way it did in KDE-3.1 again (documentation + was not updated to this KDE-version, which confused me on 2003/08/28) + +2003-11-04 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * More reorganization and preparation for getting accels right. + +2003-10-31 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Split Constructor into more subfunctions. + To be continued. + +2003-10-20 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * At last the calculator window resizes, when buttons are hidden/shown + * Added a few extra buttons to "fill gaps". + +2003-10-14 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * RadioButtons for Base and Angle converted to PopUpMenu+Button + * Layout changed + * Moved ENTER form keyPressedEvent to Accel() + +2003-10-10 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Number buttons look like numeric keyboard (on US-keyboards that is) + * Initialize ToggleActions correctly + +2003-10-09 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Reverted the menubar stuff after several complaints. + Now Kcalc-GUI looks again like on 2003-09-11. + +2003-09-30 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Fixed bug (unitialized pointers) + +2003-09-26 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Moved all type of buttons to menubars, which can be hidden/showed + via the menubar. This is quite experimental and full of bugs. + +2003-09-11 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * Button groups can be switch on/off via actions. + This is not yet the final GUI-Layout (yes, it looks broken). + * Accordingly the Stat/Trig-mode has been deleted from + configure window. + +2003-09-11 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * deleted a few #includes + +2003-09-02 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * dropped configure-button and Help-button + * created menubar with standard-actions + * ConfigDialog is not modal anymore + * copy/paste/cut-standard actions applied to calc_display + +2003-08-28 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * created Pi-button and moved Inv-button to make space for it + * label of "."-button is now localized + * Caption is set via signal/slots + * Fixed "%"-mode to make it again more conformant with documentation. + "x^y%" does still not work. Did it ever? + * Number-keys are now handled by KAccel instead of keyPressEvent + * ConfigDialog is modal + +2003-08-27 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * moved result_history from CalcEngine into DispLogic + * reactivation of rounding towards zero for cos(90) etc. + * quit is done in a more KDE conformant way + * Caption is set via slots etc. + +2003-08-12 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * continued separation: now display is independent class and + handles everything related to itself. + GUI passes only information between core and display. + +2003-08-04 Klaus Niederkrüger <kniederk@math.uni-koeln.de> + * finished the separation of gui-code from the calculating core. + this still needs some clean-up + +2003-02-11 Evan Teran <emt3734@rit.edu> + * replaced cheasy stack with STL stack classes (it really should have been + two stacks, but was mushed into one with a linked list dividing content) + * made it use new headers (no .h) when _ISOC99_SOURCE is defined + * added replace current gui code with ui files to TODO list + +2002-05-10 Evan Teran <emt3734@rit.edu> + * altered makefile to remove building of it as a library then linking that + to a dummy object file, this was silly and caused inclusion of an uneeded + source file + * bumped version to reflect new options dialog, next version will be 2.0.0 + as it will have many new changes/features + +2002-03-11 Evan Teran <emt3734@rit.edu> + * started work on making calculator code _seperate_ from the + gui code, the goal here is the make the calculating core + replacable with any library (hopfully with better precision) simply by + wrapping it in a class + * made it some many buttons are disabled when unavailabled (A-F) not enabled + unless we are in HEX mode, less confusion for users who arent familiar with + different bases + * removed some code that is never getting called + * why oh why are exceptions disabled in the standard config, I would like to + use them :( + +2001-10-18 Evan Teran <emt3734@rit.edu> + * removed configdlg.* from source tree as it is not part of the compile + * changed options dialog to use smarter layouts, and also fixed spinbox + size problem so they are now usable + * synced changed I made to the KDE 2.2.1 release version to match CVS + version which compiles under KDE 3.0 w/ QT 3.0.0 + * made sure the clear (clear entry) button functioned properly, my minor + change before broke it in some situations + + +2001-10-12 Evan Teran <emt3734@rit.edu> + * Reorganized code for all files, much more consistant now + * completely reworked the cvb (convert to binary) function + it now is sane, the last one did a rediculous amount of + unneeded work + * changed C/C++ headers to use new style as per ANSI/ISO + standard + * removed fontdlg.cpp/h from tree, not even used in compile :P + * made binary mode 32-bit + * reorganized UpdateDisplay code to make more sense + * found possible nasty memleak in EnterEqual + * now use my UNUSED macro to perform (void)var on unused parameters + to avoid compile warnings, much more readable this way + * merged setXXX functions to angle_selected/base_selected + then removed the setXXX functions as they no longer have any purpose + * changed a ton of code to use true C++ bools, makes logic + more clear + * made cvb a static member of QtCalculator instead of an ugly global + function + * changed history to use a simple vectory object instead of the storing + the values in a dynamically allocated QList, it was clearly leaking memory + as it was almost never released, this could have been fixed by enabling the + autodelete feature of QList...but why dynamically allocate when we are + storing numerical values?!? simple array with an int as an iterator :) + * changed error trapping from C style signal trapping, rather use exceptions + much cleaner that way + * removed un-used TopOfStack function + * fixed ability to enter a decimal point when in hex/oct/bin mode, those are + integer value only modes + * fixed problem with entering multiple decimal points in decimal mode + * changed CALCAMNT to be defined by a typedef, I did notice that at least my + C++ math headers are broken...functions like cos should (by newest + standards) use float, double, or long double versions automatically based on + datatype, however mine (Redhat 7.1) seems to only have the old double + versions, and have alternate names for these functions + * fixed the fact that the normal clear button seemingly did nothing + + +1999-08-22 Bernd Johannes Wuebben <wuebben@math.cornell.edu> + + * kcalc_core.cpp (UpdateDisplay): + Re-enabled the use of long double. Most if not all distributions + come now with a working glib math library. + +Mon Nov 16 18:05:01 1998 Mario Weilguni <mweilguni@kde.org> + + * There was an error in the stdev forumal. Fixed. + * the population standard deviation had the same fault. Fixed. + +Mon Nov 16 18:05:01 1998 Mario Weilguni <mweilguni@kde.org> + + * calculation the facturial of a too large number was delayed, + even though infinity was already reached. Now kcalc stops + calculation if infinity is reached and displays an error + +Mon May 4 06:28:09 1998 Bernd Johannes Wuebben <wuebben@math.cornell.edu> + + * Added the comma key as an accelerator for '.' + +Sat Apr 18 16:26:52 1998 Bernd Johannes Wuebben <wuebben@math.cornell.edu> + + * Some inverse functions didn't compute right. Wonder who broke them. + +Sun Feb 8 16:11:34 1998 Bernd Johannes Wuebben <wuebben@math.cornell.edu> + + * removed a compiler warning + +Sat Nov 22 14:30:37 1997 Bernd Johannes Wuebben <wuebben@petit.cornell.edu> + + * stats.cpp: fixed some bugs in the stats module + mean should now be correct + std shoudl now be correct too. + +Sat Sep 20 23:59:30 1997 Bernd Johannes Wuebben <wuebben@petit.cornell.edu> + + * kcalc.cpp: Added statistical functions + +Mon Sep 15 00:34:58 1997 Bernd Johannes Wuebben <wuebben@petit.cornell.edu> + + * added cut and pasted functionality + * implemented EE + * implemented result stack + * implemented precision and fixed precision + * added key bindings + * tooltips + * added configuration dialog + + +Sat Aug 2 22:06:59 1997 Bernd Johannes Wuebben <wuebben@petit.cornell.edu> + + * kcalc.h: clean up + + diff --git a/kcalc/Makefile.am b/kcalc/Makefile.am new file mode 100644 index 0000000..551d7d4 --- /dev/null +++ b/kcalc/Makefile.am @@ -0,0 +1,40 @@ +AM_CPPFLAGS= -I$(srcdir)/knumber -D_ISOC99_SOURCE $(all_includes) + +SUBDIRS = knumber + +bin_PROGRAMS = +lib_LTLIBRARIES = +kdeinit_LTLIBRARIES = kcalc.la + +kcalc_la_SOURCES = kcalc.cpp kcalc_button.cpp kcalc_const_button.cpp \ + kcalc_const_menu.cpp kcalc_core.cpp kcalcdisplay.cpp \ + dlabel.cpp stats.cpp colors.ui general.ui \ + constants.ui kcalc_settings.kcfgc + + +METASOURCES = AUTO + +noinst_HEADERS = kcalc.h kcalc_button.h kcalc_const_button.h \ + kcalc_const_menu.h kcalc_core.h kcalcdisplay.h \ + kcalctype.h dlabel.h stats.h + +kcalc_la_LDFLAGS = $(all_libraries) -module -avoid-version +kcalc_la_LIBADD = $(LIB_KDEUI) knumber/libknumber.la + +KDE_ICON = kcalc + +xdg_apps_DATA = kcalc.desktop +kde_kcfg_DATA = kcalc.kcfg + +rcdir = $(kde_datadir)/kcalc +rc_DATA = kcalcui.rc + +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/kcalc.pot + +updatedir = $(kde_datadir)/kconf_update +update_DATA = kcalcrc.upd + +DOXYGEN_EMPTY = YES +include $(top_srcdir)/admin/Doxyfile.am + diff --git a/kcalc/README b/kcalc/README new file mode 100644 index 0000000..eb64d7c --- /dev/null +++ b/kcalc/README @@ -0,0 +1,8 @@ +KCalc +===== +KCalc is currently covered under the GPL version 2. A copy of this +license can be found in a file named COPYING, in the toplevel directory. + +Have fun with kcalc! + + diff --git a/kcalc/TODO b/kcalc/TODO new file mode 100644 index 0000000..533c7d4 --- /dev/null +++ b/kcalc/TODO @@ -0,0 +1,15 @@ +== ToDo == +* find a real fix for cos 90 != 0 bug (only in double version of compile) + +* get rid of dlabel.h & dlabel.cpp +* key groups for color configuration need to be rethought +* better to handle keys with "accel" or with "keyPressEvent"? + +* think about either doing RichText by hand on labels, or only draw visible buttons, to enhance startup time. + +Following examples from the handbook do not work anymore as explained +in the documentation. Need to update the documentation!! +* 22.345 Mod 8 = will give the result 6.345 +* 10.345 Lsh 3 = also gives 80 +* 16 Inv Lsh 2 = gives 4 (16 divided by 2 twice). +* 16.999 Inv Lsh 2 = also gives 4
\ No newline at end of file diff --git a/kcalc/colors.ui b/kcalc/colors.ui new file mode 100644 index 0000000..26f4b28 --- /dev/null +++ b/kcalc/colors.ui @@ -0,0 +1,278 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>Colors</class> +<widget class="QWidget"> + <property name="name"> + <cstring>Colors</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>375</width> + <height>331</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox3</cstring> + </property> + <property name="title"> + <string>Display Colors</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>&Foreground:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_ForeColor</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel4</cstring> + </property> + <property name="text"> + <string>&Background:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_BackColor</cstring> + </property> + </widget> + <spacer row="1" column="3"> + <property name="name"> + <cstring>spacer5</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>110</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="KColorButton" row="1" column="2"> + <property name="name"> + <cstring>kcfg_BackColor</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="color"> + <color> + <red>189</red> + <green>255</green> + <blue>180</blue> + </color> + </property> + </widget> + <widget class="KColorButton" row="0" column="2"> + <property name="name"> + <cstring>kcfg_ForeColor</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="color"> + <color> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </property> + </widget> + </grid> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox4</cstring> + </property> + <property name="title"> + <string>Button Colors</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>textLabel5</cstring> + </property> + <property name="text"> + <string>&Functions:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_FunctionButtonsColor</cstring> + </property> + </widget> + <widget class="QLabel" row="2" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>textLabel7</cstring> + </property> + <property name="text"> + <string>He&xadecimals:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_HexButtonsColor</cstring> + </property> + </widget> + <widget class="QLabel" row="5" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>textLabel10</cstring> + </property> + <property name="text"> + <string>O&perations:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_OperationButtonsColor</cstring> + </property> + </widget> + <widget class="KColorButton" row="0" column="2"> + <property name="name"> + <cstring>kcfg_FunctionButtonsColor</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="KColorButton" row="1" column="2"> + <property name="name"> + <cstring>kcfg_StatButtonsColor</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="KColorButton" row="4" column="2"> + <property name="name"> + <cstring>kcfg_MemoryButtonsColor</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <spacer row="3" column="3"> + <property name="name"> + <cstring>spacer6</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>41</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="KColorButton" row="5" column="2"> + <property name="name"> + <cstring>kcfg_OperationButtonsColor</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="KColorButton" row="2" column="2"> + <property name="name"> + <cstring>kcfg_HexButtonsColor</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="QLabel" row="3" column="0"> + <property name="name"> + <cstring>textLabel8</cstring> + </property> + <property name="text"> + <string>&Numbers:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_NumberButtonsColor</cstring> + </property> + </widget> + <widget class="KColorButton" row="3" column="2"> + <property name="name"> + <cstring>kcfg_NumberButtonsColor</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel6</cstring> + </property> + <property name="text"> + <string>St&atistic functions:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_StatButtonsColor</cstring> + </property> + </widget> + <widget class="QLabel" row="4" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>textLabel9</cstring> + </property> + <property name="text"> + <string>&Memory:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_MemoryButtonsColor</cstring> + </property> + </widget> + </grid> + </widget> + <spacer> + <property name="name"> + <cstring>spacer4</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>0</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<tabstops> + <tabstop>kcfg_ForeColor</tabstop> + <tabstop>kcfg_BackColor</tabstop> + <tabstop>kcfg_FunctionButtonsColor</tabstop> + <tabstop>kcfg_StatButtonsColor</tabstop> + <tabstop>kcfg_HexButtonsColor</tabstop> + <tabstop>kcfg_NumberButtonsColor</tabstop> + <tabstop>kcfg_MemoryButtonsColor</tabstop> + <tabstop>kcfg_OperationButtonsColor</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/kcalc/configure.in.bot b/kcalc/configure.in.bot new file mode 100644 index 0000000..cb7005a --- /dev/null +++ b/kcalc/configure.in.bot @@ -0,0 +1,12 @@ +if test "x$kcalc_gmp_found" = "xno"; then + cat << EOF + +KCalc will not be compiled as you are missing the GMP library. +Please install the libgmp packages +or get GMP from http://www.swox.com/gmp/ +then run configure again + +EOF + + +fi diff --git a/kcalc/configure.in.in b/kcalc/configure.in.in new file mode 100644 index 0000000..3501f1e --- /dev/null +++ b/kcalc/configure.in.in @@ -0,0 +1,78 @@ +AC_CHECK_HEADERS(ieeefp.h) + +AC_CHECK_FUNCS(fabsl) + +AC_DEFUN([KDE_C_LONG_DOUBLE], +[ + AC_CACHE_CHECK(for long double, ac_cv_c_long_double, + [ + ac_save_LIBS="$LIBS" + LIBS="-lm $LIBS" + AC_TRY_RUN( + [ +#define _ISOC99_SOURCE 1 +#define _GNU_SOURCE 1 +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +int main() { +/* The Stardent Vistra knows sizeof(long double), but does not support it. */ +long double foo = 1.0; +char buffer[10]; +/* On Ultrix 4.3 cc, long double is 4 and double is 8. */ +int result = (sizeof(long double) <= sizeof(double)); +/* the following is needed for a broken printf in glibc2 */ +if (!result) { + foo = foo * 3; + sprintf(buffer,"%0.0Lf",foo); + result = strcmp(buffer, "3"); +/* and now something mean ;-) */ + foo = powl(fabsl(foo), 1); +} +exit(result); } + ], + ac_cv_c_long_double=yes, ac_cv_c_long_double=no, + ac_cv_c_long_double=no + ) + LIBS="$ac_save_LIBS" + ]) + if test $ac_cv_c_long_double = yes; then + AC_DEFINE(HAVE_LONG_DOUBLE, 1, [Define if you have support for long double in printf]) + fi +]) +KDE_C_LONG_DOUBLE + +have_l_funcs=yes +AC_CHECK_LIB(m, asinl,,have_l_funcs=no) +AC_CHECK_LIB(m, sqrtl,,have_l_funcs=no) + +if test "xyes" = "x$have_l_funcs" ; then + AC_DEFINE(HAVE_L_FUNCS,1,[Define if you have *l math functions (absl, ...)]) +fi + +AC_LANG_C +AC_CHECK_LIB(m, isinf, [ + AC_DEFINE_UNQUOTED(HAVE_FUNC_ISINF, 1, [Define if you have isinf]) +]) +AC_CHECK_LIB(m, round, [ + AC_DEFINE_UNQUOTED(HAVE_FUNC_ROUND, 1, [Define if you have round]) +]) +AC_CHECK_LIB(m, roundl, [ + AC_DEFINE_UNQUOTED(HAVE_FUNC_ROUNDL, 1, [Define if you have round]) +]) + +kcalc_gmp_found=yes +LIBGMP= +KDE_CHECK_HEADER([gmp.h], [ + KDE_CHECK_LIB(gmp, main, [ + LIBGMP="-lgmp" + AC_DEFINE(HAVE_GMP, 1, [Define if you have libgmp]) + ]) + ],[ + DO_NOT_COMPILE="kcalc $DO_NOT_COMPILE" + kcalc_gmp_found=no + ] +) +AC_SUBST(LIBGMP) diff --git a/kcalc/confvalues.h b/kcalc/confvalues.h new file mode 100644 index 0000000..0ec1fae --- /dev/null +++ b/kcalc/confvalues.h @@ -0,0 +1,48 @@ +/* + + KCalc + + Copyright (C) Bernd Johannes Wuebben + wuebben@math.cornell.edu + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + */ + + +#ifndef _CONF_VALUES_H_ +#define _CONF_VALUES_H_ + +typedef struct _DefStruct +{ + QColor forecolor; + QColor backcolor; + QColor numberButtonColor; + QColor functionButtonColor; + QColor statButtonColor; + QColor hexButtonColor; + QColor memoryButtonColor; + QColor operationButtonColor; + + int precision; + int fixedprecision; + bool fixed; + bool beep; + bool capres; + QFont font; +} DefStruct; + +#endif // _CONF_VALUES_H_ diff --git a/kcalc/constants.ui b/kcalc/constants.ui new file mode 100644 index 0000000..f7c734e --- /dev/null +++ b/kcalc/constants.ui @@ -0,0 +1,491 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>Constants</class> +<widget class="QWidget"> + <property name="name"> + <cstring>Constants</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>534</width> + <height>596</height> + </rect> + </property> + <property name="caption"> + <string>Constants</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox"> + <property name="name"> + <cstring>mainGroupBox</cstring> + </property> + <property name="title"> + <string>Configure Constants</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox0</cstring> + </property> + <property name="title"> + <string>C1</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLineEdit"> + <property name="name"> + <cstring>kcfg_nameConstant0</cstring> + </property> + <property name="maxLength"> + <number>6</number> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>70</width> + <height>21</height> + </size> + </property> + </spacer> + <widget class="QLineEdit"> + <property name="name"> + <cstring>kcfg_valueConstant0</cstring> + </property> + <property name="maxLength"> + <number>40</number> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>80</width> + <height>21</height> + </size> + </property> + </spacer> + <widget class="KPushButton"> + <property name="name"> + <cstring>kPushButton0</cstring> + </property> + <property name="text"> + <string>Predefined</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="title"> + <string>C2</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLineEdit"> + <property name="name"> + <cstring>kcfg_nameConstant1</cstring> + </property> + <property name="maxLength"> + <number>6</number> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer3</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>70</width> + <height>21</height> + </size> + </property> + </spacer> + <widget class="QLineEdit"> + <property name="name"> + <cstring>kcfg_valueConstant1</cstring> + </property> + <property name="maxLength"> + <number>40</number> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer4</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>80</width> + <height>21</height> + </size> + </property> + </spacer> + <widget class="KPushButton"> + <property name="name"> + <cstring>kPushButton1</cstring> + </property> + <property name="text"> + <string>Predefined</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox2</cstring> + </property> + <property name="title"> + <string>C3</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLineEdit"> + <property name="name"> + <cstring>kcfg_nameConstant2</cstring> + </property> + <property name="maxLength"> + <number>6</number> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer5</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>70</width> + <height>21</height> + </size> + </property> + </spacer> + <widget class="QLineEdit"> + <property name="name"> + <cstring>kcfg_valueConstant2</cstring> + </property> + <property name="maxLength"> + <number>40</number> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer6</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>80</width> + <height>21</height> + </size> + </property> + </spacer> + <widget class="KPushButton"> + <property name="name"> + <cstring>kPushButton2</cstring> + </property> + <property name="text"> + <string>Predefined</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox3</cstring> + </property> + <property name="title"> + <string>C4</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLineEdit"> + <property name="name"> + <cstring>kcfg_nameConstant3</cstring> + </property> + <property name="maxLength"> + <number>6</number> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer7</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>70</width> + <height>21</height> + </size> + </property> + </spacer> + <widget class="QLineEdit"> + <property name="name"> + <cstring>kcfg_valueConstant3</cstring> + </property> + <property name="maxLength"> + <number>40</number> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer8</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>80</width> + <height>21</height> + </size> + </property> + </spacer> + <widget class="KPushButton"> + <property name="name"> + <cstring>kPushButton3</cstring> + </property> + <property name="text"> + <string>Predefined</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox4</cstring> + </property> + <property name="title"> + <string>C5</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLineEdit"> + <property name="name"> + <cstring>kcfg_nameConstant4</cstring> + </property> + <property name="maxLength"> + <number>6</number> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer9</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>70</width> + <height>21</height> + </size> + </property> + </spacer> + <widget class="QLineEdit"> + <property name="name"> + <cstring>kcfg_valueConstant4</cstring> + </property> + <property name="maxLength"> + <number>40</number> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer10</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>80</width> + <height>21</height> + </size> + </property> + </spacer> + <widget class="KPushButton"> + <property name="name"> + <cstring>kPushButton4</cstring> + </property> + <property name="text"> + <string>Predefined</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox5</cstring> + </property> + <property name="title"> + <string>C6</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLineEdit"> + <property name="name"> + <cstring>kcfg_nameConstant5</cstring> + </property> + <property name="maxLength"> + <number>6</number> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer11</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>70</width> + <height>21</height> + </size> + </property> + </spacer> + <widget class="QLineEdit"> + <property name="name"> + <cstring>kcfg_valueConstant5</cstring> + </property> + <property name="maxLength"> + <number>40</number> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer12</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>80</width> + <height>21</height> + </size> + </property> + </spacer> + <widget class="KPushButton"> + <property name="name"> + <cstring>kPushButton5</cstring> + </property> + <property name="text"> + <string>Predefined</string> + </property> + </widget> + </hbox> + </widget> + </vbox> + </widget> + <spacer> + <property name="name"> + <cstring>spacer13</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> +</includehints> +</UI> diff --git a/kcalc/dlabel.cpp b/kcalc/dlabel.cpp new file mode 100644 index 0000000..8c6c062 --- /dev/null +++ b/kcalc/dlabel.cpp @@ -0,0 +1,184 @@ +/* + $Id$ + + KCalc, a scientific calculator for the X window system using the + Qt widget libraries, available at no cost at http://www.troll.no + + Copyright (C) 1996 Bernd Johannes Wuebben + wuebben@math.cornell.edu + + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include <qglobal.h> +#include <kactioncollection.h> +#include <kstdaction.h> + +#include "kcalc_settings.h" +#include "kcalc_core.h" +#include "dlabel.h" +#include "dlabel.moc" + + + +DispLogic::DispLogic(QWidget *parent, const char *name, + KActionCollection *coll) + :KCalcDisplay(parent,name), _history_index(0) +{ + KNumber::setDefaultFloatOutput(true); + KNumber::setDefaultFractionalInput(true); + _back = KStdAction::undo(this, SLOT(history_back()), coll); + _forward = KStdAction::redo(this, SLOT(history_forward()), coll); + + _forward->setEnabled(false); + _back->setEnabled(false); +} + +DispLogic::~DispLogic() +{ +} + +void DispLogic::changeSettings() +{ + QPalette pal = palette(); + + pal.setColor(QColorGroup::Text, KCalcSettings::foreColor()); + pal.setColor(QColorGroup::Foreground, KCalcSettings::foreColor()); + pal.setColor(QColorGroup::Background, KCalcSettings::backColor()); + + setPalette(pal); + setBackgroundColor(KCalcSettings::backColor()); + + setFont(KCalcSettings::font()); + + setPrecision(KCalcSettings::precision()); + + if(KCalcSettings::fixed() == false) + setFixedPrecision(-1); + else + setFixedPrecision(KCalcSettings::fixedPrecision()); + + setBeep(KCalcSettings::beep()); + setGroupDigits(KCalcSettings::groupDigits()); + updateDisplay(); +} + +void DispLogic::update_from_core(CalcEngine const &core, + bool store_result_in_history) +{ + bool tmp_error; + KNumber const & output = core.lastOutput(tmp_error); + if(tmp_error) sendEvent(EventError); + if (setAmount(output) && store_result_in_history && + output != KNumber::Zero) + { + // add this latest value to our history + _history_list.insert(_history_list.begin(), output); + _history_index = 0; + _back->setEnabled(true); + _forward->setEnabled(false); + } +} + +void DispLogic::EnterDigit(int data) +{ + char tmp; + switch(data) + { + case 0: + tmp = '0'; + break; + case 1: + tmp = '1'; + break; + case 2: + tmp = '2'; + break; + case 3: + tmp = '3'; + break; + case 4: + tmp = '4'; + break; + case 5: + tmp = '5'; + break; + case 6: + tmp = '6'; + break; + case 7: + tmp = '7'; + break; + case 8: + tmp = '8'; + break; + case 9: + tmp = '9'; + break; + case 0xA: + tmp = 'A'; + break; + case 0xB: + tmp = 'B'; + break; + case 0xC: + tmp = 'C'; + break; + case 0xD: + tmp = 'D'; + break; + case 0xE: + tmp = 'E'; + break; + case 0xF: + tmp = 'F'; + break; + default: + tmp = '?'; + break; + } + + newCharacter(tmp); +} + +void DispLogic::history_forward() +{ + Q_ASSERT(! _history_list.empty()); + Q_ASSERT(_history_index > 0); + + _history_index --; + + setAmount(_history_list[_history_index]); + + if(_history_index == 0) _forward->setEnabled(false); + + _back->setEnabled(true); +} + +void DispLogic::history_back() +{ + Q_ASSERT(! _history_list.empty()); + Q_ASSERT( _history_index < static_cast<int>(_history_list.size()) ); + + setAmount(_history_list[_history_index]); + + _history_index ++; + + if( _history_index == static_cast<int>(_history_list.size()) ) + _back->setEnabled(false); + _forward->setEnabled(true); +} + diff --git a/kcalc/dlabel.h b/kcalc/dlabel.h new file mode 100644 index 0000000..a9c33c6 --- /dev/null +++ b/kcalc/dlabel.h @@ -0,0 +1,64 @@ +/* + + $Id$ + + KCalc + + Copyright (C) Bernd Johannes Wuebben + wuebben@math.cornell.edu + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + */ + + +#ifndef _D_LABEL_H_ +#define _D_LABEL_H_ + +#include <qvaluevector.h> +#include "kcalcdisplay.h" + +class CalcEngine; +class KAction; +class KActionCollection; + +class DispLogic : public KCalcDisplay +{ +Q_OBJECT + +public: + DispLogic(QWidget *parent, const char *name, + KActionCollection *coll); + ~DispLogic(); + + void changeSettings(); + void EnterDigit(int data); + void update_from_core(CalcEngine const &core, + bool store_result_in_history = false); + +private slots: + void history_back(void); + void history_forward(void); + +private: + QValueVector<KNumber> _history_list; + int _history_index; + + KAction *_forward; + KAction *_back; +}; + +#endif diff --git a/kcalc/general.ui b/kcalc/general.ui new file mode 100644 index 0000000..7ec8b15 --- /dev/null +++ b/kcalc/general.ui @@ -0,0 +1,199 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>General</class> +<widget class="QWidget"> + <property name="name"> + <cstring>General</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>295</width> + <height>262</height> + </rect> + </property> + <property name="caption"> + <string>General</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="title"> + <string>Precision</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox" row="1" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>kcfg_Fixed</cstring> + </property> + <property name="text"> + <string>Set &decimal precision</string> + </property> + </widget> + <widget class="QLabel" row="2" column="1"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Decimal &digits:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_FixedPrecision</cstring> + </property> + </widget> + <widget class="QSpinBox" row="2" column="2"> + <property name="name"> + <cstring>kcfg_FixedPrecision</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + </widget> + <spacer row="2" column="0"> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>21</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QLabel" row="0" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>&Maximum number of digits:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_Fixed</cstring> + </property> + </widget> + <spacer row="1" column="3"> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>101</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QSpinBox" row="0" column="2"> + <property name="name"> + <cstring>kcfg_Precision</cstring> + </property> + </widget> + </grid> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox2</cstring> + </property> + <property name="title"> + <string>Misc</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_Beep</cstring> + </property> + <property name="text"> + <string>&Beep on error</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_CaptionResult</cstring> + </property> + <property name="text"> + <string>Show &result in window title</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_GroupDigits</cstring> + </property> + <property name="text"> + <string>Group digits</string> + </property> + </widget> + </vbox> + </widget> + <spacer> + <property name="name"> + <cstring>spacer3</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>31</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<connections> + <connection> + <sender>kcfg_Fixed</sender> + <signal>toggled(bool)</signal> + <receiver>kcfg_FixedPrecision</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>kcfg_Fixed</sender> + <signal>toggled(bool)</signal> + <receiver>textLabel1</receiver> + <slot>setEnabled(bool)</slot> + </connection> +</connections> +<tabstops> + <tabstop>kcfg_Precision</tabstop> + <tabstop>kcfg_Fixed</tabstop> + <tabstop>kcfg_FixedPrecision</tabstop> + <tabstop>kcfg_Beep</tabstop> + <tabstop>kcfg_CaptionResult</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/kcalc/hi16-app-kcalc.png b/kcalc/hi16-app-kcalc.png Binary files differnew file mode 100644 index 0000000..deb6fcd --- /dev/null +++ b/kcalc/hi16-app-kcalc.png diff --git a/kcalc/hi22-app-kcalc.png b/kcalc/hi22-app-kcalc.png Binary files differnew file mode 100644 index 0000000..8ef1df8 --- /dev/null +++ b/kcalc/hi22-app-kcalc.png diff --git a/kcalc/hi32-app-kcalc.png b/kcalc/hi32-app-kcalc.png Binary files differnew file mode 100644 index 0000000..3406316 --- /dev/null +++ b/kcalc/hi32-app-kcalc.png diff --git a/kcalc/hi48-app-kcalc.png b/kcalc/hi48-app-kcalc.png Binary files differnew file mode 100644 index 0000000..3da02ad --- /dev/null +++ b/kcalc/hi48-app-kcalc.png diff --git a/kcalc/hi64-app-kcalc.png b/kcalc/hi64-app-kcalc.png Binary files differnew file mode 100644 index 0000000..5ebe853 --- /dev/null +++ b/kcalc/hi64-app-kcalc.png diff --git a/kcalc/hisc-app-kcalc.svgz b/kcalc/hisc-app-kcalc.svgz Binary files differnew file mode 100644 index 0000000..4690fb4 --- /dev/null +++ b/kcalc/hisc-app-kcalc.svgz diff --git a/kcalc/kcalc.cpp b/kcalc/kcalc.cpp new file mode 100644 index 0000000..e7599cf --- /dev/null +++ b/kcalc/kcalc.cpp @@ -0,0 +1,2306 @@ +/* + kCalculator, a simple scientific calculator for KDE + + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include "../config.h" + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + + +#include <qbuttongroup.h> +#include <qfont.h> +#include <qhbuttongroup.h> +#include <qlayout.h> +#include <qobjectlist.h> +#include <qradiobutton.h> +#include <qspinbox.h> +#include <qstyle.h> +#include <qtooltip.h> + + + +#include <kaboutdata.h> +#include <kaccel.h> +#include <kaction.h> +#include <kapplication.h> +#include <kcmdlineargs.h> +#include <kcolorbutton.h> +#include <kcolordrag.h> +#include <kconfig.h> +#include <kconfigdialog.h> +#include <kdialog.h> +#include <kfontdialog.h> +#include <kglobal.h> +#include <kglobalsettings.h> +#include <kkeydialog.h> +#include <kmenubar.h> +#include <knotifyclient.h> +#include <knumvalidator.h> +#include <kpopupmenu.h> +#include <kpushbutton.h> +#include <kstatusbar.h> +#include <kstdaction.h> + +#include "dlabel.h" +#include "kcalc.h" +#include "kcalc_const_menu.h" +#include "version.h" +#include "general.h" +#include "colors.h" +#include "constants.h" +#include <kaccelmanager.h> +#include "kcalc_settings.h" + + + +static const char description[] = I18N_NOOP("KDE Calculator"); +static const char version[] = KCALCVERSION; + + +KCalculator::KCalculator(QWidget *parent, const char *name) + : KMainWindow(parent, name), inverse(false), + hyp_mode(false), memory_num(0.0), calc_display(NULL), + mInternalSpacing(4), core() +{ + /* central widget to contain all the elements */ + QWidget *central = new QWidget(this); + setCentralWidget(central); + KAcceleratorManager::setNoAccel( central ); + + // Detect color change + connect(kapp,SIGNAL(kdisplayPaletteChanged()), SLOT(set_colors())); + + calc_display = new DispLogic(central, "display", actionCollection()); + + setupMainActions(); + + setupStatusbar(); + + createGUI(); + + // How can I make the toolBar not appear at all? + // This is not a nice solution. + toolBar()->close(); + + // Create Button to select BaseMode + BaseChooseGroup = new QHButtonGroup(i18n("Base"), central); + connect(BaseChooseGroup, SIGNAL(clicked(int)), SLOT(slotBaseSelected(int))); + BaseChooseGroup->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed, false); + + + pbBaseChoose[0] = new QRadioButton(i18n("He&x"), BaseChooseGroup, + "Hexadecimal-Switch"); + QToolTip::add(pbBaseChoose[0], i18n("Switch base to hexadecimal.")); + + pbBaseChoose[1] = new QRadioButton(i18n("&Dec"), BaseChooseGroup, + "Decimal-Switch"); + QToolTip::add(pbBaseChoose[1], i18n("Switch base to decimal.")); + + pbBaseChoose[2] = new QRadioButton(i18n("&Oct"), BaseChooseGroup, + "Octal-Switch"); + QToolTip::add(pbBaseChoose[2], i18n("Switch base to octal.")); + + pbBaseChoose[3] = new QRadioButton(i18n("&Bin"), BaseChooseGroup, + "Binary-Switch"); + QToolTip::add(pbBaseChoose[3], i18n("Switch base to binary.")); + + + // Create Button to select AngleMode + pbAngleChoose = new QPushButton(i18n("&Angle"), + central, "ChooseAngleMode-Button"); + QToolTip::add(pbAngleChoose, i18n("Choose the unit for the angle measure")); + pbAngleChoose->setAutoDefault(false); + + KPopupMenu *angle_menu = new KPopupMenu(pbAngleChoose, "AngleMode-Selection-Menu"); + angle_menu->insertItem(i18n("Degrees"), 0); + angle_menu->insertItem(i18n("Radians"), 1); + angle_menu->insertItem(i18n("Gradians"), 2); + + angle_menu->setCheckable(true); + connect(angle_menu, SIGNAL(activated(int)), SLOT(slotAngleSelected(int))); + pbAngleChoose->setPopup(angle_menu); + + + + pbInv = new KCalcButton("Inv", central, "Inverse-Button", + i18n("Inverse mode")); + pbInv->setAccel(Key_I); + connect(pbInv, SIGNAL(toggled(bool)), SLOT(slotInvtoggled(bool))); + connect(this, SIGNAL(switchShowAccels(bool)), + pbInv, SLOT(slotSetAccelDisplayMode(bool))); + pbInv->setToggleButton(true); + + // + // Create Calculator Buttons + // + + // First the widgets that are the parents of the buttons + mSmallPage = new QWidget(central); + mLargePage = new QWidget(central); + mNumericPage = setupNumericKeys(central); + + setupLogicKeys(mSmallPage); + setupStatisticKeys(mSmallPage); + setupScientificKeys(mSmallPage); + setupConstantsKeys(mSmallPage); + + + pbMod = new KCalcButton(mSmallPage, "Modulo-Button"); + pbMod->addMode(ModeNormal, "Mod", i18n("Modulo")); + pbMod->addMode(ModeInverse, "IntDiv", i18n("Integer division")); + pbMod->setAccel(Key_Colon); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + pbMod, SLOT(slotSetMode(ButtonModeFlags,bool))); + connect(this, SIGNAL(switchShowAccels(bool)), + pbMod, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbMod, SIGNAL(clicked(void)), SLOT(slotModclicked(void))); + + pbReci = new KCalcButton(mSmallPage, "Reciprocal-Button"); + pbReci->addMode(ModeNormal, "1/x", i18n("Reciprocal")); + pbReci->setAccel(Key_R); + connect(this, SIGNAL(switchShowAccels(bool)), + pbReci, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbReci, SIGNAL(clicked(void)), SLOT(slotReciclicked(void))); + + pbFactorial = new KCalcButton(mSmallPage, "Factorial-Button"); + pbFactorial->addMode(ModeNormal, "x!", i18n("Factorial")); + pbFactorial->setAccel(Key_Exclam); + connect(this, SIGNAL(switchShowAccels(bool)), + pbFactorial, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbFactorial, SIGNAL(clicked(void)),SLOT(slotFactorialclicked(void))); + + // Representation of x^2 is moved to the function + // changeRepresentation() that paints the letters When + // pressing the INV Button a sqrt symbol will be drawn on that + // button + pbSquare = new KCalcButton(mSmallPage, "Square-Button"); + pbSquare->addMode(ModeNormal, "x<sup>2</sup>", i18n("Square"), true); + pbSquare->addMode(ModeInverse, "x<sup>3</sup>", i18n("Third power"), true); + connect(this, SIGNAL(switchShowAccels(bool)), + pbSquare, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + pbSquare, SLOT(slotSetMode(ButtonModeFlags,bool))); + connect(pbSquare, SIGNAL(clicked(void)), SLOT(slotSquareclicked(void))); + + pbRoot = new KSquareButton(mSmallPage, "Square-Button"); + pbRoot->addMode(ModeNormal, "sqrt(x)", i18n("Square root")); + pbRoot->addMode(ModeInverse, "sqrt[3](x)", i18n("Cube root")); + connect(this, SIGNAL(switchShowAccels(bool)), + pbRoot, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + pbRoot, SLOT(slotSetMode(ButtonModeFlags,bool))); + connect(pbRoot, SIGNAL(clicked(void)), SLOT(slotRootclicked(void))); + + + // Representation of x^y is moved to the function + // changeRepresentation() that paints the letters When + // pressing the INV Button y^x will be drawn on that button + pbPower = new KCalcButton(mSmallPage, "Power-Button"); + pbPower->addMode(ModeNormal, "x<sup>y</sup>", i18n("x to the power of y"), true); + pbPower->addMode(ModeInverse, "x<sup>1/y</sup>", i18n("x to the power of 1/y"), true); + connect(this, SIGNAL(switchShowAccels(bool)), + pbPower, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + pbPower, SLOT(slotSetMode(ButtonModeFlags,bool))); + pbPower->setAccel(Key_AsciiCircum); + connect(pbPower, SIGNAL(clicked(void)), SLOT(slotPowerclicked(void))); + + + // + // All these layouts are needed because all the groups have their + // own size per row so we can't use one huge QGridLayout (mosfet) + // + QGridLayout *smallBtnLayout = new QGridLayout(mSmallPage, 6, 4, 0, + mInternalSpacing); + QGridLayout *largeBtnLayout = new QGridLayout(mLargePage, 5, 2, 0, + mInternalSpacing); + + QHBoxLayout *topLayout = new QHBoxLayout(); + QHBoxLayout *btnLayout = new QHBoxLayout(); + + // bring them all together + QVBoxLayout *mainLayout = new QVBoxLayout(central, mInternalSpacing, + mInternalSpacing); + + mainLayout->addLayout(topLayout); + mainLayout->addLayout(btnLayout); + + // button layout + btnLayout->addWidget(mSmallPage, 0, AlignTop); + btnLayout->addSpacing(2*mInternalSpacing); + btnLayout->addWidget(mNumericPage, 0, AlignTop); + btnLayout->addSpacing(2*mInternalSpacing); + btnLayout->addWidget(mLargePage, 0, AlignTop); + + // small button layout + smallBtnLayout->addWidget(pbStat["NumData"], 0, 0); + smallBtnLayout->addWidget(pbScientific["HypMode"], 0, 1); + smallBtnLayout->addWidget(pbLogic["AND"], 0, 2); + smallBtnLayout->addWidget(pbMod, 0, 3); + smallBtnLayout->addWidget(NumButtonGroup->find(0xA), 0, 4); + smallBtnLayout->addWidget(pbConstant[0], 0, 5); + + smallBtnLayout->addWidget(pbStat["Mean"], 1, 0); + smallBtnLayout->addWidget(pbScientific["Sine"], 1, 1); + smallBtnLayout->addWidget(pbLogic["OR"], 1, 2); + smallBtnLayout->addWidget(pbReci, 1, 3); + smallBtnLayout->addWidget(NumButtonGroup->find(0xB), 1, 4); + smallBtnLayout->addWidget(pbConstant[1], 1, 5); + + smallBtnLayout->addWidget(pbStat["StandardDeviation"], 2, 0); + smallBtnLayout->addWidget(pbScientific["Cosine"], 2, 1); + smallBtnLayout->addWidget(pbLogic["XOR"], 2, 2); + smallBtnLayout->addWidget(pbFactorial, 2, 3); + smallBtnLayout->addWidget(NumButtonGroup->find(0xC), 2, 4); + smallBtnLayout->addWidget(pbConstant[2], 2, 5); + + smallBtnLayout->addWidget(pbStat["Median"], 3, 0); + smallBtnLayout->addWidget(pbScientific["Tangent"], 3, 1); + smallBtnLayout->addWidget(pbLogic["LeftShift"], 3, 2); + smallBtnLayout->addWidget(pbSquare, 3, 3); + smallBtnLayout->addWidget(NumButtonGroup->find(0xD), 3, 4); + smallBtnLayout->addWidget(pbConstant[3], 3, 5); + + smallBtnLayout->addWidget(pbStat["InputData"], 4, 0); + smallBtnLayout->addWidget(pbScientific["Log10"], 4, 1); + smallBtnLayout->addWidget(pbLogic["RightShift"], 4, 2); + smallBtnLayout->addWidget(pbRoot, 4, 3); + smallBtnLayout->addWidget(NumButtonGroup->find(0xE), 4, 4); + smallBtnLayout->addWidget(pbConstant[4], 4, 5); + + smallBtnLayout->addWidget(pbStat["ClearData"], 5, 0); + smallBtnLayout->addWidget(pbScientific["LogNatural"], 5, 1); + smallBtnLayout->addWidget(pbLogic["One-Complement"], 5, 2); + smallBtnLayout->addWidget(pbPower, 5, 3); + smallBtnLayout->addWidget(NumButtonGroup->find(0xF), 5, 4); + smallBtnLayout->addWidget(pbConstant[5], 5, 5); + + smallBtnLayout->setRowStretch(0, 0); + smallBtnLayout->setRowStretch(1, 0); + smallBtnLayout->setRowStretch(2, 0); + smallBtnLayout->setRowStretch(3, 0); + smallBtnLayout->setRowStretch(4, 0); + smallBtnLayout->setRowStretch(5, 0); + + // large button layout + largeBtnLayout->addWidget(pbClear, 0, 0); + largeBtnLayout->addWidget(pbAC, 0, 1); + + largeBtnLayout->addWidget(pbParenOpen, 1, 0); + largeBtnLayout->addWidget(pbParenClose, 1, 1); + + largeBtnLayout->addWidget(pbMemRecall, 2, 0); + largeBtnLayout->addWidget(pbMemStore, 2, 1); + + largeBtnLayout->addWidget(pbMemPlusMinus, 3, 0); + largeBtnLayout->addWidget(pbMC, 3, 1); + + largeBtnLayout->addWidget(pbPercent, 4, 0); + largeBtnLayout->addWidget(pbPlusMinus, 4, 1); + + // top layout + topLayout->addWidget(pbAngleChoose); + topLayout->addWidget(BaseChooseGroup); + topLayout->addStretch(); + topLayout->addWidget(pbInv); + mainLayout->insertWidget(0, calc_display); + + mFunctionButtonList.append(pbScientific["HypMode"]); + mFunctionButtonList.append(pbInv); + mFunctionButtonList.append(pbRoot); + mFunctionButtonList.append(pbScientific["Sine"]); + mFunctionButtonList.append(pbPlusMinus); + mFunctionButtonList.append(pbScientific["Cosine"]); + mFunctionButtonList.append(pbReci); + mFunctionButtonList.append(pbScientific["Tangent"]); + mFunctionButtonList.append(pbFactorial); + mFunctionButtonList.append(pbScientific["Log10"]); + mFunctionButtonList.append(pbSquare); + mFunctionButtonList.append(pbScientific["LogNatural"]); + mFunctionButtonList.append(pbPower); + + mMemButtonList.append(pbEE); + mMemButtonList.append(pbMemRecall); + mMemButtonList.append(pbMemPlusMinus); + mMemButtonList.append(pbMemStore); + mMemButtonList.append(pbMC); + mMemButtonList.append(pbClear); + mMemButtonList.append(pbAC); + + mOperationButtonList.append(pbX); + mOperationButtonList.append(pbParenOpen); + mOperationButtonList.append(pbParenClose); + mOperationButtonList.append(pbLogic["AND"]); + mOperationButtonList.append(pbDivision); + mOperationButtonList.append(pbLogic["OR"]); + mOperationButtonList.append(pbLogic["XOR"]); + mOperationButtonList.append(pbPlus); + mOperationButtonList.append(pbMinus); + mOperationButtonList.append(pbLogic["LeftShift"]); + mOperationButtonList.append(pbLogic["RightShift"]); + mOperationButtonList.append(pbPeriod); + mOperationButtonList.append(pbEqual); + mOperationButtonList.append(pbPercent); + mOperationButtonList.append(pbLogic["One-Complement"]); + mOperationButtonList.append(pbMod); + + set_colors(); + // Show the result in the app's caption in taskbar (wishlist - bug #52858) + if (KCalcSettings::captionResult() == true) + connect(calc_display, + SIGNAL(changedText(const QString &)), + SLOT(setCaption(const QString &))); + calc_display->changeSettings(); + set_precision(); + + // Switch to decimal + resetBase(); + slotAngleSelected(0); + + updateGeometry(); + + adjustSize(); + setFixedSize(sizeHint()); + + UpdateDisplay(true); + + // Read and set button groups + + actionStatshow->setChecked(KCalcSettings::showStat()); + slotStatshow(KCalcSettings::showStat()); + + actionScientificshow->setChecked(KCalcSettings::showScientific()); + slotScientificshow(KCalcSettings::showScientific()); + + actionLogicshow->setChecked(KCalcSettings::showLogic()); + slotLogicshow(KCalcSettings::showLogic()); + + actionConstantsShow->setChecked(KCalcSettings::showConstants()); + slotConstantsShow(KCalcSettings::showConstants()); +} + +KCalculator::~KCalculator() +{ + KCalcSettings::writeConfig(); + delete calc_display; +} + +void KCalculator::setupMainActions(void) +{ + // file menu + KStdAction::quit(this, SLOT(close()), actionCollection()); + + // edit menu + KStdAction::cut(calc_display, SLOT(slotCut()), actionCollection()); + KStdAction::copy(calc_display, SLOT(slotCopy()), actionCollection()); + KStdAction::paste(calc_display, SLOT(slotPaste()), actionCollection()); + + // settings menu + actionStatshow = new KToggleAction(i18n("&Statistic Buttons"), 0, + actionCollection(), "show_stat"); + actionStatshow->setChecked(true); + connect(actionStatshow, SIGNAL(toggled(bool)), + SLOT(slotStatshow(bool))); + + actionScientificshow = new KToggleAction(i18n("Science/&Engineering Buttons"), + 0, actionCollection(), "show_science"); + actionScientificshow->setChecked(true); + connect(actionScientificshow, SIGNAL(toggled(bool)), + SLOT(slotScientificshow(bool))); + + actionLogicshow = new KToggleAction(i18n("&Logic Buttons"), 0, + actionCollection(), "show_logic"); + actionLogicshow->setChecked(true); + connect(actionLogicshow, SIGNAL(toggled(bool)), + SLOT(slotLogicshow(bool))); + + actionConstantsShow = new KToggleAction(i18n("&Constants Buttons"), 0, + actionCollection(), "show_constants"); + actionConstantsShow->setChecked(true); + connect(actionConstantsShow, SIGNAL(toggled(bool)), + SLOT(slotConstantsShow(bool))); + + + (void) new KAction(i18n("&Show All"), 0, this, SLOT(slotShowAll()), + actionCollection(), "show_all"); + + (void) new KAction(i18n("&Hide All"), 0, this, SLOT(slotHideAll()), + actionCollection(), "hide_all"); + + KStdAction::preferences(this, SLOT(showSettings()), actionCollection()); + + KStdAction::keyBindings(guiFactory(), SLOT(configureShortcuts()), +actionCollection()); + +} + +void KCalculator::setupStatusbar(void) +{ + // Status bar contents + statusBar()->insertFixedItem(" NORM ", 0, true); + statusBar()->setItemAlignment(0, AlignCenter); + + statusBar()->insertFixedItem(" HEX ", 1, true); + statusBar()->setItemAlignment(1, AlignCenter); + + statusBar()->insertFixedItem(" DEG ", 2, true); + statusBar()->setItemAlignment(2, AlignCenter); + + statusBar()->insertFixedItem(" \xa0\xa0 ", 3, true); // Memory indicator + statusBar()->setItemAlignment(3, AlignCenter); +} + +QWidget* KCalculator::setupNumericKeys(QWidget *parent) +{ + Q_CHECK_PTR(mSmallPage); + Q_CHECK_PTR(mLargePage); + + QWidget *thisPage = new QWidget(parent); + + KCalcButton *tmp_pb; + + NumButtonGroup = new QButtonGroup(0, "Num-Button-Group"); + connect(NumButtonGroup, SIGNAL(clicked(int)), + SLOT(slotNumberclicked(int))); + + tmp_pb = new KCalcButton("0", thisPage, "0-Button"); + tmp_pb->setAccel(Key_0); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 0); + + tmp_pb = new KCalcButton("1", thisPage, "1-Button"); + tmp_pb->setAccel(Key_1); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 1); + + tmp_pb = new KCalcButton("2", thisPage, "2-Button"); + tmp_pb->setAccel(Key_2); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 2); + + tmp_pb = new KCalcButton("3", thisPage, "3-Button"); + tmp_pb->setAccel(Key_3); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 3); + + tmp_pb = new KCalcButton("4", thisPage, "4-Button"); + tmp_pb->setAccel(Key_4); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 4); + + tmp_pb = new KCalcButton("5", thisPage, "5-Button"); + tmp_pb->setAccel(Key_5); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 5); + + tmp_pb = new KCalcButton("6", thisPage, "6-Button"); + tmp_pb->setAccel(Key_6); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 6); + + tmp_pb = new KCalcButton("7", thisPage, "7-Button"); + tmp_pb->setAccel(Key_7); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 7); + + tmp_pb = new KCalcButton("8", thisPage, "8-Button"); + tmp_pb->setAccel(Key_8); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 8); + + tmp_pb = new KCalcButton("9", thisPage, "9-Button"); + tmp_pb->setAccel(Key_9); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 9); + + pbEE = new KCalcButton(thisPage, "EE-Button"); + pbEE->addMode(ModeNormal, "x<small>" "\xb7" "10</small><sup>y</sup>", + i18n("Exponent"), true); + pbEE->setAccel(Key_E); + connect(this, SIGNAL(switchShowAccels(bool)), + pbEE, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbEE, SIGNAL(clicked(void)), SLOT(slotEEclicked(void))); + + pbParenClose = new KCalcButton(")", mLargePage, "ParenClose-Button"); + pbParenClose->setAccel(Key_ParenRight); + connect(this, SIGNAL(switchShowAccels(bool)), + pbParenClose, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbParenClose,SIGNAL(clicked(void)),SLOT(slotParenCloseclicked(void))); + + pbX = new KCalcButton("X", thisPage, "Multiply-Button", i18n("Multiplication")); + pbX->setAccel(Key_multiply); + connect(this, SIGNAL(switchShowAccels(bool)), + pbX, SLOT(slotSetAccelDisplayMode(bool))); + accel()->insert("Pressed '*'", i18n("Pressed Multiplication-Button"), + 0, Key_Asterisk, pbX, SLOT(animateClick())); + connect(pbX, SIGNAL(clicked(void)), SLOT(slotXclicked(void))); + + pbDivision = new KCalcButton("/", thisPage, "Division-Button", i18n("Division")); + pbDivision->setAccel(Key_Slash); + connect(this, SIGNAL(switchShowAccels(bool)), + pbDivision, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbDivision, SIGNAL(clicked(void)), SLOT(slotDivisionclicked(void))); + + pbPlus = new KCalcButton("+", thisPage, "Plus-Button", i18n("Addition")); + connect(this, SIGNAL(switchShowAccels(bool)), + pbPlus, SLOT(slotSetAccelDisplayMode(bool))); + pbPlus->setAccel(Key_Plus); + connect(pbPlus, SIGNAL(clicked(void)), SLOT(slotPlusclicked(void))); + + pbMinus = new KCalcButton("-", thisPage, "Minus-Button", i18n("Subtraction")); + pbMinus->setAccel(Key_Minus); + connect(this, SIGNAL(switchShowAccels(bool)), + pbMinus, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbMinus, SIGNAL(clicked(void)), SLOT(slotMinusclicked(void))); + + pbPeriod = new KCalcButton(KGlobal::locale()->decimalSymbol(), thisPage, + "Period-Button", i18n("Decimal point")); + connect(this, SIGNAL(switchShowAccels(bool)), + pbPeriod, SLOT(slotSetAccelDisplayMode(bool))); + accel()->insert("Decimal Point (Period)", i18n("Pressed Decimal Point"), + 0, Key_Period, pbPeriod, SLOT(animateClick())); + accel()->insert("Decimal Point (Comma)", i18n("Pressed Decimal Point"), + 0, Key_Comma, pbPeriod, SLOT(animateClick())); + connect(pbPeriod, SIGNAL(clicked(void)), SLOT(slotPeriodclicked(void))); + + pbEqual = new KCalcButton("=", thisPage, "Equal-Button", i18n("Result")); + pbEqual->setAccel(Key_Enter); + connect(this, SIGNAL(switchShowAccels(bool)), + pbEqual, SLOT(slotSetAccelDisplayMode(bool))); + accel()->insert("Entered Equal", i18n("Pressed Equal-Button"), + 0, Key_Equal, pbEqual, SLOT(animateClick())); + accel()->insert("Entered Return", i18n("Pressed Equal-Button"), + 0, Key_Return, pbEqual, SLOT(animateClick())); + connect(pbEqual, SIGNAL(clicked(void)), SLOT(slotEqualclicked(void))); + + + QGridLayout *thisLayout = new QGridLayout(thisPage, 5, 4, 0, + mInternalSpacing); + + // large button layout + thisLayout->addWidget(pbEE, 0, 0); + thisLayout->addWidget(pbDivision, 0, 1); + thisLayout->addWidget(pbX, 0, 2); + thisLayout->addWidget(pbMinus, 0, 3); + + thisLayout->addWidget(NumButtonGroup->find(7), 1, 0); + thisLayout->addWidget(NumButtonGroup->find(8), 1, 1); + thisLayout->addWidget(NumButtonGroup->find(9), 1, 2); + thisLayout->addMultiCellWidget(pbPlus, 1, 2, 3, 3); + + thisLayout->addWidget(NumButtonGroup->find(4), 2, 0); + thisLayout->addWidget(NumButtonGroup->find(5), 2, 1); + thisLayout->addWidget(NumButtonGroup->find(6), 2, 2); + //thisLayout->addMultiCellWidget(pbPlus, 1, 2, 3, 3); + + thisLayout->addWidget(NumButtonGroup->find(1), 3, 0); + thisLayout->addWidget(NumButtonGroup->find(2), 3, 1); + thisLayout->addWidget(NumButtonGroup->find(3), 3, 2); + thisLayout->addMultiCellWidget(pbEqual, 3, 4, 3, 3); + + thisLayout->addMultiCellWidget(NumButtonGroup->find(0), 4, 4, 0, 1); + thisLayout->addWidget(pbPeriod, 4, 2); + //thisLayout->addMultiCellWidget(pbEqual, 3, 4, 3, 3); + + thisLayout->addColSpacing(0,10); + thisLayout->addColSpacing(1,10); + thisLayout->addColSpacing(2,10); + thisLayout->addColSpacing(3,10); + thisLayout->addColSpacing(4,10); + + + pbMemRecall = new KCalcButton("MR", mLargePage, "MemRecall-Button", i18n("Memory recall")); + connect(this, SIGNAL(switchShowAccels(bool)), + pbMemRecall, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbMemRecall, SIGNAL(clicked(void)), + SLOT(slotMemRecallclicked(void))); + pbMemRecall->setDisabled(true); // At start, there is nothing in memory + + pbMemPlusMinus = new KCalcButton(mLargePage, "MPlusMinus-Button"); + pbMemPlusMinus->addMode(ModeNormal, "M+", i18n("Add display to memory")); + pbMemPlusMinus->addMode(ModeInverse, "M-", i18n("Subtract from memory")); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + pbMemPlusMinus, SLOT(slotSetMode(ButtonModeFlags,bool))); + connect(this, SIGNAL(switchShowAccels(bool)), + pbMemPlusMinus, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbMemPlusMinus,SIGNAL(clicked(void)), + SLOT(slotMemPlusMinusclicked(void))); + + pbMemStore = new KCalcButton("MS", mLargePage, "MemStore-Button", + i18n("Memory store")); + connect(this, SIGNAL(switchShowAccels(bool)), + pbMemStore, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbMemStore, SIGNAL(clicked(void)), SLOT(slotMemStoreclicked(void))); + + + pbMC = new KCalcButton("MC", mLargePage, "MemClear-Button", i18n("Clear memory")); + connect(this, SIGNAL(switchShowAccels(bool)), + pbMC, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbMC, SIGNAL(clicked(void)), SLOT(slotMCclicked(void))); + + pbClear = new KCalcButton("C", mLargePage, "Clear-Button", i18n("Clear")); + pbClear->setAccel(Key_Prior); + connect(this, SIGNAL(switchShowAccels(bool)), + pbClear, SLOT(slotSetAccelDisplayMode(bool))); + accel()->insert("Entered 'ESC'", i18n("Pressed ESC-Button"), 0, + Key_Escape, pbClear, SLOT(animateClick())); + connect(pbClear, SIGNAL(clicked(void)), SLOT(slotClearclicked(void))); + + pbAC = new KCalcButton("AC", mLargePage, "AC-Button", i18n("Clear all")); + pbAC->setAccel(Key_Delete); + connect(this, SIGNAL(switchShowAccels(bool)), + pbAC, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbAC, SIGNAL(clicked(void)), SLOT(slotACclicked(void))); + + pbParenOpen = new KCalcButton("(", mLargePage, "ParenOpen-Button"); + pbParenOpen->setAccel(Key_ParenLeft); + connect(this, SIGNAL(switchShowAccels(bool)), + pbParenOpen, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbParenOpen, SIGNAL(clicked(void)),SLOT(slotParenOpenclicked(void))); + + pbPercent = new KCalcButton("%", mLargePage, "Percent-Button", i18n("Percent")); + pbPercent->setAccel(Key_Percent); + connect(this, SIGNAL(switchShowAccels(bool)), + pbPercent, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbPercent, SIGNAL(clicked(void)), SLOT(slotPercentclicked(void))); + + pbPlusMinus = new KCalcButton("\xb1", mLargePage, "Sign-Button", i18n("Change sign")); + pbPlusMinus->setAccel(Key_Backslash); + connect(this, SIGNAL(switchShowAccels(bool)), + pbPlusMinus, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbPlusMinus, SIGNAL(clicked(void)), SLOT(slotPlusMinusclicked(void))); + + + tmp_pb = new KCalcButton("A", mSmallPage, "A-Button"); + tmp_pb->setAccel(Key_A); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 0xA); + + tmp_pb = new KCalcButton("B", mSmallPage, "B-Button"); + tmp_pb->setAccel(Key_B); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 0xB); + + tmp_pb = new KCalcButton("C", mSmallPage, "C-Button"); + tmp_pb->setAccel(Key_C); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 0xC); + + tmp_pb = new KCalcButton("D", mSmallPage, "D-Button"); + tmp_pb->setAccel(Key_D); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 0xD); + + tmp_pb = new KCalcButton("E", mSmallPage, "E-Button"); + tmp_pb->setAccel(Key_E); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 0xE); + + tmp_pb = new KCalcButton("F", mSmallPage, "F-Button"); + tmp_pb->setAccel(Key_F); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 0xF); + + return thisPage; +} + +void KCalculator::setupLogicKeys(QWidget *parent) +{ + Q_CHECK_PTR(parent); + + KCalcButton *tmp_pb; + + tmp_pb = new KCalcButton("AND", parent, "AND-Button", i18n("Bitwise AND")); + pbLogic.insert("AND", tmp_pb); + tmp_pb->setAccel(Key_Ampersand); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(tmp_pb, SIGNAL(clicked(void)), SLOT(slotANDclicked(void))); + + tmp_pb = new KCalcButton("OR", parent, "OR-Button", i18n("Bitwise OR")); + pbLogic.insert("OR", tmp_pb); + tmp_pb->setAccel(Key_Bar); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(tmp_pb, SIGNAL(clicked(void)), SLOT(slotORclicked(void))); + + tmp_pb = new KCalcButton("XOR", parent, "XOR-Button", i18n("Bitwise XOR")); + pbLogic.insert("XOR", tmp_pb); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(tmp_pb, SIGNAL(clicked(void)), SLOT(slotXORclicked(void))); + + tmp_pb = new KCalcButton("Cmp", parent, "One-Complement-Button", + i18n("One's complement")); + pbLogic.insert("One-Complement", tmp_pb); + tmp_pb->setAccel(Key_AsciiTilde); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(tmp_pb, SIGNAL(clicked(void)), SLOT(slotNegateclicked(void))); + + tmp_pb = new KCalcButton("Lsh", parent, "LeftBitShift-Button", + i18n("Left bit shift")); + tmp_pb->setAccel(Key_Less); + pbLogic.insert("LeftShift", tmp_pb); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(tmp_pb, SIGNAL(clicked(void)), + SLOT(slotLeftShiftclicked(void))); + + tmp_pb = new KCalcButton("Rsh", parent, "RightBitShift-Button", + i18n("Right bit shift")); + tmp_pb->setAccel(Key_Greater); + pbLogic.insert("RightShift", tmp_pb); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(tmp_pb, SIGNAL(clicked(void)), + SLOT(slotRightShiftclicked(void))); +} + +void KCalculator::setupScientificKeys(QWidget *parent) +{ + Q_CHECK_PTR(parent); + + KCalcButton *tmp_pb; + + tmp_pb = new KCalcButton("Hyp", parent, "Hyp-Button", i18n("Hyperbolic mode")); + pbScientific.insert("HypMode", tmp_pb); + tmp_pb->setAccel(Key_H); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(tmp_pb, SIGNAL(toggled(bool)), SLOT(slotHyptoggled(bool))); + tmp_pb->setToggleButton(true); + + tmp_pb = new KCalcButton(parent, "Sin-Button"); + pbScientific.insert("Sine", tmp_pb); + tmp_pb->addMode(ModeNormal, "Sin", i18n("Sine")); + tmp_pb->addMode(ModeInverse, "Asin", i18n("Arc sine")); + tmp_pb->addMode(ModeHyperbolic, "Sinh", i18n("Hyperbolic sine")); + tmp_pb->addMode(ButtonModeFlags(ModeInverse | ModeHyperbolic), + "Asinh", i18n("Inverse hyperbolic sine")); + tmp_pb->setAccel(Key_S); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + connect(tmp_pb, SIGNAL(clicked(void)), SLOT(slotSinclicked(void))); + + tmp_pb = new KCalcButton(parent, "Cos-Button"); + pbScientific.insert("Cosine", tmp_pb); + tmp_pb->addMode(ModeNormal, "Cos", i18n("Cosine")); + tmp_pb->addMode(ModeInverse, "Acos", i18n("Arc cosine")); + tmp_pb->addMode(ModeHyperbolic, "Cosh", i18n("Hyperbolic cosine")); + tmp_pb->addMode(ButtonModeFlags(ModeInverse | ModeHyperbolic), + "Acosh", i18n("Inverse hyperbolic cosine")); + tmp_pb->setAccel(Key_C); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + connect(tmp_pb, SIGNAL(clicked(void)), SLOT(slotCosclicked(void))); + + tmp_pb = new KCalcButton(parent, "Tan-Button"); + pbScientific.insert("Tangent", tmp_pb); + tmp_pb->addMode(ModeNormal, "Tan", i18n("Tangent")); + tmp_pb->addMode(ModeInverse, "Atan", i18n("Arc tangent")); + tmp_pb->addMode(ModeHyperbolic, "Tanh", i18n("Hyperbolic tangent")); + tmp_pb->addMode(ButtonModeFlags(ModeInverse | ModeHyperbolic), + "Atanh", i18n("Inverse hyperbolic tangent")); + tmp_pb->setAccel(Key_T); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + connect(tmp_pb, SIGNAL(clicked(void)),SLOT(slotTanclicked(void))); + + tmp_pb = new KCalcButton(parent, "Ln-Button"); + tmp_pb->addMode(ModeNormal, "Ln", i18n("Natural log")); + tmp_pb->addMode(ModeInverse, "e<sup> x </sup>", i18n("Exponential function"), + true); + pbScientific.insert("LogNatural", tmp_pb); + tmp_pb->setAccel(Key_N); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + connect(tmp_pb, SIGNAL(clicked(void)), SLOT(slotLnclicked(void))); + + tmp_pb = new KCalcButton(parent, "Log-Button"); + tmp_pb->addMode(ModeNormal, "Log", i18n("Logarithm to base 10")); + tmp_pb->addMode(ModeInverse, "10<sup> x </sup>", i18n("10 to the power of x"), + true); + pbScientific.insert("Log10", tmp_pb); + tmp_pb->setAccel(Key_L); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + connect(tmp_pb, SIGNAL(clicked(void)), SLOT(slotLogclicked(void))); + +} + +void KCalculator::setupStatisticKeys(QWidget *parent) +{ + Q_CHECK_PTR(parent); + + KCalcButton *tmp_pb; + + tmp_pb = new KCalcButton(parent, "Stat.NumData-Button"); + tmp_pb->addMode(ModeNormal, "N", i18n("Number of data entered")); + tmp_pb->addMode(ModeInverse, QString::fromUtf8("\xce\xa3") + + "x", i18n("Sum of all data items")); + pbStat.insert("NumData", tmp_pb); + mStatButtonList.append(tmp_pb); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + connect(tmp_pb, SIGNAL(clicked(void)), SLOT(slotStatNumclicked(void))); + + tmp_pb = new KCalcButton(parent, "Stat.Median-Button"); + tmp_pb->addMode(ModeNormal, "Med", i18n("Median")); + pbStat.insert("Median", tmp_pb); + mStatButtonList.append(tmp_pb); + QToolTip::add(tmp_pb, i18n("Median")); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(tmp_pb, SIGNAL(clicked(void)), SLOT(slotStatMedianclicked(void))); + + tmp_pb = new KCalcButton(parent, "Stat.Mean-Button"); + tmp_pb->addMode(ModeNormal, "Mea", i18n("Mean")); + tmp_pb->addMode(ModeInverse, QString::fromUtf8("\xce\xa3") + + "x<sup>2</sup>", + i18n("Sum of all data items squared"), true); + pbStat.insert("Mean", tmp_pb); + mStatButtonList.append(tmp_pb); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + connect(tmp_pb, SIGNAL(clicked(void)), SLOT(slotStatMeanclicked(void))); + + tmp_pb = new KCalcButton(parent, "Stat.StandardDeviation-Button"); + tmp_pb->addMode(ModeNormal, QString::fromUtf8("Ď",-1) + "<sub>N-1</sub>", + i18n("Sample standard deviation"), true); + tmp_pb->addMode(ModeInverse, QString::fromUtf8("Ď",-1) + "<sub>N</sub>", + i18n("Standard deviation"), true); + pbStat.insert("StandardDeviation", tmp_pb); + mStatButtonList.append(tmp_pb); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + connect(tmp_pb, SIGNAL(clicked(void)), SLOT(slotStatStdDevclicked(void))); + + tmp_pb = new KCalcButton(parent, "Stat.DataInput-Button"); + tmp_pb->addMode(ModeNormal, "Dat", i18n("Enter data")); + tmp_pb->addMode(ModeInverse, "CDat", i18n("Delete last data item")); + pbStat.insert("InputData", tmp_pb); + mStatButtonList.append(tmp_pb); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + connect(tmp_pb, SIGNAL(clicked(void)), SLOT(slotStatDataInputclicked(void))); + + tmp_pb = new KCalcButton(parent, "Stat.ClearData-Button"); + tmp_pb->addMode(ModeNormal, "CSt", i18n("Clear data store")); + pbStat.insert("ClearData", tmp_pb); + mStatButtonList.append(tmp_pb); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(tmp_pb, SIGNAL(clicked(void)), SLOT(slotStatClearDataclicked(void))); +} + +void KCalculator::setupConstantsKeys(QWidget *parent) +{ + Q_CHECK_PTR(parent); + + ConstButtonGroup = new QButtonGroup(0, "Const-Button-Group"); + connect(ConstButtonGroup, SIGNAL(clicked(int)), SLOT(slotConstclicked(int))); + + + KCalcConstButton *tmp_pb; + tmp_pb = new KCalcConstButton(parent, 0, "C1"); + tmp_pb->setAccel(ALT + Key_1); + pbConstant[0] = tmp_pb; + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + ConstButtonGroup->insert(tmp_pb, 0); + + tmp_pb = new KCalcConstButton(parent, 1, "C2"); + tmp_pb->setAccel(ALT + Key_2); + pbConstant[1] = tmp_pb; + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + ConstButtonGroup->insert(tmp_pb, 1); + + tmp_pb = new KCalcConstButton(parent, 2, "C3"); + tmp_pb->setAccel(ALT + Key_3); + pbConstant[2] = tmp_pb; + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + ConstButtonGroup->insert(tmp_pb, 2); + + tmp_pb = new KCalcConstButton(parent, 3, "C4"); + tmp_pb->setAccel(ALT + Key_4); + pbConstant[3] = tmp_pb; + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + ConstButtonGroup->insert(tmp_pb, 3); + + tmp_pb = new KCalcConstButton(parent, 4, "C5"); + tmp_pb->setAccel(ALT + Key_5); + pbConstant[4] = tmp_pb; + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + ConstButtonGroup->insert(tmp_pb, 4); + + tmp_pb = new KCalcConstButton(parent, 5, "C6"); + tmp_pb->setAccel(ALT + Key_6); + pbConstant[5] = tmp_pb; + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + ConstButtonGroup->insert(tmp_pb, 5); + + changeButtonNames(); + + // add menu with scientific constants + KCalcConstMenu *tmp_menu = new KCalcConstMenu(this); + menuBar()->insertItem(i18n("&Constants"), tmp_menu, -1, 2); + connect(tmp_menu, SIGNAL(activated(int)), this, + SLOT(slotConstantToDisplay(int))); +} + +void KCalculator::slotConstantToDisplay(int constant) +{ + calc_display->setAmount(KCalcConstMenu::Constants[constant].value); + + UpdateDisplay(false); +} + +void KCalculator::updateGeometry(void) +{ + QObjectList *l; + QSize s; + int margin; + + // + // Calculator buttons + // + s.setWidth(mSmallPage->fontMetrics().width("MMMM")); + s.setHeight(mSmallPage->fontMetrics().lineSpacing()); + + // why this stupid cast! + l = const_cast<QObjectList *>(mSmallPage->children()); + + for(uint i=0; i < l->count(); i++) + { + QObject *o = l->at(i); + if( o->isWidgetType() ) + { + QWidget *tmp_widget = dynamic_cast<QWidget *>(o); + margin = QApplication::style(). + pixelMetric(QStyle::PM_ButtonMargin, (tmp_widget))*2; + tmp_widget->setFixedSize(s.width()+margin, s.height()+margin); + //tmp_widget->setMinimumSize(s.width()+margin, s.height()+margin); + tmp_widget->installEventFilter( this ); + tmp_widget->setAcceptDrops(true); + } + } + + // why this stupic cast !! + l = const_cast<QObjectList*>(mLargePage->children()); + + int h1 = (NumButtonGroup->find(0x0F))->minimumSize().height(); + int h2 = static_cast<int>( (static_cast<float>(h1) + 4.0) / 5.0 ); + s.setWidth(mLargePage->fontMetrics().width("MMM") + + QApplication::style(). + pixelMetric(QStyle::PM_ButtonMargin, NumButtonGroup->find(0x0F))*2); + s.setHeight(h1 + h2); + + for(uint i = 0; i < l->count(); i++) + { + QObject *o = l->at(i); + if(o->isWidgetType()) + { + QWidget *tmp_widget = dynamic_cast<QWidget *>(o); + tmp_widget->setFixedSize(s); + tmp_widget->installEventFilter(this); + tmp_widget->setAcceptDrops(true); + } + } + + pbInv->setFixedSize(s); + pbInv->installEventFilter(this); + pbInv->setAcceptDrops(true); + + + + l = (QObjectList*)mNumericPage->children(); // silence please + + h1 = (NumButtonGroup->find(0x0F))->minimumSize().height(); + h2 = (int)((((float)h1 + 4.0) / 5.0)); + s.setWidth(mLargePage->fontMetrics().width("MMM") + + QApplication::style(). + pixelMetric(QStyle::PM_ButtonMargin, NumButtonGroup->find(0x0F))*2); + s.setHeight(h1 + h2); + + for(uint i = 0; i < l->count(); i++) + { + QObject *o = l->at(i); + if(o->isWidgetType()) + { + QWidget *tmp_widget = dynamic_cast<QWidget *>(o); + tmp_widget->setFixedSize(s); + tmp_widget->installEventFilter(this); + tmp_widget->setAcceptDrops(true); + } + } + + // Set Buttons of double size + QSize t(s); + t.setWidth(2*s.width()); + NumButtonGroup->find(0x00)->setFixedSize(t); + t = s; + t.setHeight(2*s.height()); + pbEqual->setFixedSize(t); + pbPlus->setFixedSize(t); +} + +void KCalculator::slotBaseSelected(int base) +{ + int current_base; + + // set display & statusbar (if item exist in statusbar) + switch(base) + { + case 3: + current_base = calc_display->setBase(NumBase(2)); + if (statusBar()->hasItem(1)) statusBar()->changeItem("BIN",1); + calc_display->setStatusText(1, "Bin"); + break; + case 2: + current_base = calc_display->setBase(NumBase(8)); + if (statusBar()->hasItem(1)) statusBar()->changeItem("OCT",1); + calc_display->setStatusText(1, "Oct"); + break; + case 1: + current_base = calc_display->setBase(NumBase(10)); + if (statusBar()->hasItem(1)) statusBar()->changeItem("DEC",1); + calc_display->setStatusText(1, "Dec"); + break; + case 0: + current_base = calc_display->setBase(NumBase(16)); + if (statusBar()->hasItem(1)) statusBar()->changeItem("HEX",1); + calc_display->setStatusText(1, "Hex"); + break; + default: + if (statusBar()->hasItem(1)) statusBar()->changeItem("Error",1); + calc_display->setStatusText(1, "Error"); + return; + } + + // Enable the buttons not available in this base + for (int i=0; i<current_base; i++) + NumButtonGroup->find(i)->setEnabled (true); + + // Disable the buttons not available in this base + for (int i=current_base; i<16; i++) + NumButtonGroup->find(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) + { + pbScientific["HypMode"]->setEnabled(false); + pbScientific["Sine"]->setEnabled(false); + pbScientific["Cosine"]->setEnabled(false); + pbScientific["Tangent"]->setEnabled(false); + pbScientific["LogNatural"]->setEnabled(false); + pbScientific["Log10"]->setEnabled(false); + } + else + { + pbScientific["HypMode"]->setEnabled(true); + pbScientific["Sine"]->setEnabled(true); + pbScientific["Cosine"]->setEnabled(true); + pbScientific["Tangent"]->setEnabled(true); + pbScientific["LogNatural"]->setEnabled(true); + pbScientific["Log10"]->setEnabled(true); + } +} + +void KCalculator::keyPressEvent(QKeyEvent *e) +{ + if ( ( e->state() & KeyButtonMask ) == 0 || ( e->state() & ShiftButton ) ) { + switch (e->key()) + { + case Key_Next: + pbAC->animateClick(); + break; + case Key_Slash: + case Key_division: + pbDivision->animateClick(); + break; + case Key_D: + pbStat["InputData"]->animateClick(); // stat mode + break; + case Key_BracketLeft: + case Key_twosuperior: + pbSquare->animateClick(); + break; + case Key_Backspace: + calc_display->deleteLastDigit(); + // pbAC->animateClick(); + break; + } + } + + if (e->key() == Key_Control) + emit switchShowAccels(true); +} + +void KCalculator::keyReleaseEvent(QKeyEvent *e) +{ + if (e->key() == Key_Control) + emit switchShowAccels(false); +} + +void KCalculator::slotAngleSelected(int number) +{ + pbAngleChoose->popup()->setItemChecked(0, false); + pbAngleChoose->popup()->setItemChecked(1, false); + pbAngleChoose->popup()->setItemChecked(2, false); + + switch(number) + { + case 0: + _angle_mode = DegMode; + statusBar()->changeItem("DEG", 2); + pbAngleChoose->popup()->setItemChecked(0, true); + calc_display->setStatusText(2, "Deg"); + break; + case 1: + _angle_mode = RadMode; + statusBar()->changeItem("RAD", 2); + pbAngleChoose->popup()->setItemChecked(1, true); + calc_display->setStatusText(2, "Rad"); + break; + case 2: + _angle_mode = GradMode; + statusBar()->changeItem("GRA", 2); + pbAngleChoose->popup()->setItemChecked(2, true); + calc_display->setStatusText(2, "Gra"); + break; + default: // we shouldn't ever end up here + _angle_mode = RadMode; + } +} + +void KCalculator::slotEEclicked(void) +{ + calc_display->newCharacter('e'); +} + +void KCalculator::slotInvtoggled(bool flag) +{ + inverse = flag; + + emit switchMode(ModeInverse, flag); + + if (inverse) + { + statusBar()->changeItem("INV", 0); + calc_display->setStatusText(0, "Inv"); + } + else + { + statusBar()->changeItem("NORM", 0); + calc_display->setStatusText(0, QString::null); + } +} + +void KCalculator::slotHyptoggled(bool flag) +{ + // toggle between hyperbolic and standart trig functions + hyp_mode = flag; + + emit switchMode(ModeHyperbolic, flag); +} + + + +void KCalculator::slotMemRecallclicked(void) +{ + // temp. work-around + calc_display->sendEvent(KCalcDisplay::EventReset); + + calc_display->setAmount(memory_num); + UpdateDisplay(false); +} + +void KCalculator::slotMemStoreclicked(void) +{ + EnterEqual(); + + memory_num = calc_display->getAmount(); + calc_display->setStatusText(3, "M"); + statusBar()->changeItem("M",3); + pbMemRecall->setEnabled(true); +} + +void KCalculator::slotNumberclicked(int number_clicked) +{ + calc_display->EnterDigit(number_clicked); +} + +void KCalculator::slotSinclicked(void) +{ + if (hyp_mode) + { + // sinh or arsinh + if (!inverse) + core.SinHyp(calc_display->getAmount()); + else + core.AreaSinHyp(calc_display->getAmount()); + } + else + { + // sine or arcsine + if (!inverse) + 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(true); +} + +void KCalculator::slotPlusMinusclicked(void) +{ + // 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(true); + } +} + +void KCalculator::slotMemPlusMinusclicked(void) +{ + bool tmp_inverse = inverse; // store this, because next command deletes inverse + EnterEqual(); // finish calculation so far, to store result into MEM + + if (!tmp_inverse) memory_num += calc_display->getAmount(); + else memory_num -= calc_display->getAmount(); + + pbInv->setOn(false); + statusBar()->changeItem("M",3); + calc_display->setStatusText(3, "M"); + pbMemRecall->setEnabled(true); +} + +void KCalculator::slotCosclicked(void) +{ + if (hyp_mode) + { + // cosh or arcosh + if (!inverse) + core.CosHyp(calc_display->getAmount()); + else + core.AreaCosHyp(calc_display->getAmount()); + } + else + { + // cosine or arccosine + if (!inverse) + 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(true); +} + +void KCalculator::slotReciclicked(void) +{ + core.Reciprocal(calc_display->getAmount()); + UpdateDisplay(true); +} + +void KCalculator::slotTanclicked(void) +{ + if (hyp_mode) + { + // tanh or artanh + if (!inverse) + core.TangensHyp(calc_display->getAmount()); + else + core.AreaTangensHyp(calc_display->getAmount()); + } + else + { + // tan or arctan + if (!inverse) + 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(true); +} + +void KCalculator::slotFactorialclicked(void) +{ + core.Factorial(calc_display->getAmount()); + + UpdateDisplay(true); +} + +void KCalculator::slotLogclicked(void) +{ + if (!inverse) + core.Log10(calc_display->getAmount()); + else + core.Exp10(calc_display->getAmount()); + + UpdateDisplay(true); +} + + +void KCalculator::slotSquareclicked(void) +{ + if (!inverse) + core.Square(calc_display->getAmount()); + else + core.Cube(calc_display->getAmount()); + + UpdateDisplay(true); +} + +void KCalculator::slotRootclicked(void) +{ + if (!inverse) + core.SquareRoot(calc_display->getAmount()); + else + core.CubeRoot(calc_display->getAmount()); + + UpdateDisplay(true); +} + +void KCalculator::slotLnclicked(void) +{ + if (!inverse) + core.Ln(calc_display->getAmount()); + else + core.Exp(calc_display->getAmount()); + + UpdateDisplay(true); +} + +void KCalculator::slotPowerclicked(void) +{ + if (inverse) + { + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_PWR_ROOT); + pbInv->setOn(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(false); +} + +void KCalculator::slotMCclicked(void) +{ + memory_num = 0; + statusBar()->changeItem(" \xa0\xa0 ",3); + calc_display->setStatusText(3, QString::null); + pbMemRecall->setDisabled(true); +} + +void KCalculator::slotClearclicked(void) +{ + calc_display->sendEvent(KCalcDisplay::EventClear); +} + +void KCalculator::slotACclicked(void) +{ + core.Reset(); + calc_display->sendEvent(KCalcDisplay::EventReset); + + UpdateDisplay(true); +} + +void KCalculator::slotParenOpenclicked(void) +{ + core.ParenOpen(calc_display->getAmount()); + + // What behavior, if e.g.: "12(6*6)"?? + //UpdateDisplay(true); +} + +void KCalculator::slotParenCloseclicked(void) +{ + core.ParenClose(calc_display->getAmount()); + + UpdateDisplay(true); +} + +void KCalculator::slotANDclicked(void) +{ + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_AND); + + UpdateDisplay(true); +} + +void KCalculator::slotXclicked(void) +{ + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_MULTIPLY); + + UpdateDisplay(true); +} + +void KCalculator::slotDivisionclicked(void) +{ + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_DIVIDE); + + UpdateDisplay(true); +} + +void KCalculator::slotORclicked(void) +{ + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_OR); + + UpdateDisplay(true); +} + +void KCalculator::slotXORclicked(void) +{ + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_XOR); + + UpdateDisplay(true); +} + +void KCalculator::slotPlusclicked(void) +{ + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_ADD); + + UpdateDisplay(true); +} + +void KCalculator::slotMinusclicked(void) +{ + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_SUBTRACT); + + UpdateDisplay(true); +} + +void KCalculator::slotLeftShiftclicked(void) +{ + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_LSH); + + UpdateDisplay(true); +} + +void KCalculator::slotRightShiftclicked(void) +{ + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_RSH); + + UpdateDisplay(true); +} + +void KCalculator::slotPeriodclicked(void) +{ + calc_display->newCharacter('.'); +} + +void KCalculator::EnterEqual() +{ + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_EQUAL); + + UpdateDisplay(true, true); +} + +void KCalculator::slotEqualclicked(void) +{ + EnterEqual(); +} + +void KCalculator::slotPercentclicked(void) +{ + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_PERCENT); + + UpdateDisplay(true); +} + +void KCalculator::slotNegateclicked(void) +{ + core.Complement(calc_display->getAmount()); + + UpdateDisplay(true); +} + +void KCalculator::slotModclicked(void) +{ + if (inverse) + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_INTDIV); + else + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_MOD); + + UpdateDisplay(true); +} + +void KCalculator::slotStatNumclicked(void) +{ + if(!inverse) + { + core.StatCount(0); + } + else + { + pbInv->setOn(false); + core.StatSum(0); + } + + UpdateDisplay(true); +} + +void KCalculator::slotStatMeanclicked(void) +{ + if(!inverse) + core.StatMean(0); + else + { + pbInv->setOn(false); + core.StatSumSquares(0); + } + + UpdateDisplay(true); +} + +void KCalculator::slotStatStdDevclicked(void) +{ + if(inverse) + { + // std (n-1) + core.StatStdDeviation(0); + pbInv->setOn(false); + } + else + { + // std (n) + core.StatStdSample(0); + } + + UpdateDisplay(true); +} + +void KCalculator::slotStatMedianclicked(void) +{ + if(!inverse) + { + // std (n-1) + core.StatMedian(0); + } + else + { + // std (n) + core.StatMedian(0); + pbInv->setOn(false); + } + // it seems two different modes should be implemented, but...? + UpdateDisplay(true); +} + +void KCalculator::slotStatDataInputclicked(void) +{ + if(!inverse) + { + core.StatDataNew(calc_display->getAmount()); + } + else + { + pbInv->setOn(false); + core.StatDataDel(0); + statusBar()->message(i18n("Last stat item erased"), 3000); + } + + UpdateDisplay(true); +} + +void KCalculator::slotStatClearDataclicked(void) +{ + if(!inverse) + { + core.StatClearAll(0); + statusBar()->message(i18n("Stat mem cleared"), 3000); + } + else + { + pbInv->setOn(false); + UpdateDisplay(false); + } +} + +void KCalculator::slotConstclicked(int button) +{ + if(!inverse) + { + //set the display to the configured value of Constant Button + calc_display->setAmount(pbConstant[button]->constant()); + } + else + { + pbInv->setOn(false); + KCalcSettings::setValueConstant(button, calc_display->text()); + // below set new tooltip + pbConstant[button]->setLabelAndTooltip(); + // work around: after storing a number, pressing a digit should start + // a new number + calc_display->setAmount(calc_display->getAmount()); + } + + UpdateDisplay(false); +} + +void KCalculator::showSettings() +{ + // Check if there is already a dialog and if so bring + // it to the foreground. + if(KConfigDialog::showDialog("settings")) + return; + + // Create a new dialog with the same name as the above checking code. + KConfigDialog *dialog = new KConfigDialog(this, "settings", KCalcSettings::self()); + dialog->enableButtonSeparator( true ); + + // Add the general page. Store the settings in the General group and + // use the icon package_settings. + General *general = new General(0, "General"); + int maxprec = 1000; + general->kcfg_Precision->setMaxValue(maxprec); + dialog->addPage(general, i18n("General"), "package_settings", i18n("General Settings")); + + QWidget *fontWidget = new QWidget(0,"Font"); + QVBoxLayout *fontLayout = new QVBoxLayout(fontWidget); + KFontChooser *mFontChooser = + new KFontChooser(fontWidget, "kcfg_Font", false, QStringList(), false, 6); + + fontLayout->addWidget(mFontChooser); + dialog->addPage(fontWidget, i18n("Font"), "fonts", i18n("Select Display Font")); + + // color settings + + Colors *color = new Colors(0, "Color"); + + dialog->addPage(color, i18n("Colors"), "colors", i18n("Button & Display Colors")); + + // constant settings + + Constants *constant = new Constants(0, "Constant" ); + tmp_const = constant; + + KCalcConstMenu *tmp_menu = new KCalcConstMenu(this); + connect(tmp_menu, SIGNAL(activated(int)), + SLOT(slotChooseScientificConst0(int))); + (constant->kPushButton0)->setPopup(tmp_menu); + + tmp_menu = new KCalcConstMenu(this); + connect(tmp_menu, SIGNAL(activated(int)), + SLOT(slotChooseScientificConst1(int))); + (constant->kPushButton1)->setPopup(tmp_menu); + + tmp_menu = new KCalcConstMenu(this); + connect(tmp_menu, SIGNAL(activated(int)), + SLOT(slotChooseScientificConst2(int))); + (constant->kPushButton2)->setPopup(tmp_menu); + + tmp_menu = new KCalcConstMenu(this); + connect(tmp_menu, SIGNAL(activated(int)), + SLOT(slotChooseScientificConst3(int))); + (constant->kPushButton3)->setPopup(tmp_menu); + + tmp_menu = new KCalcConstMenu(this); + connect(tmp_menu, SIGNAL(activated(int)), + SLOT(slotChooseScientificConst4(int))); + (constant->kPushButton4)->setPopup(tmp_menu); + + tmp_menu = new KCalcConstMenu(this); + connect(tmp_menu, SIGNAL(activated(int)), + SLOT(slotChooseScientificConst5(int))); + (constant->kPushButton5)->setPopup(tmp_menu); + + dialog->addPage(constant, i18n("Constants"), "constants"); + + + // When the user clicks OK or Apply we want to update our settings. + connect(dialog, SIGNAL(settingsChanged()), SLOT(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!! +void KCalculator::slotChooseScientificConst0(int option) +{ + (tmp_const->kcfg_valueConstant0)->setText(KCalcConstMenu::Constants[option].value); + + (tmp_const->kcfg_nameConstant0)->setText(KCalcConstMenu::Constants[option].label); +} + +void KCalculator::slotChooseScientificConst1(int option) +{ + (tmp_const->kcfg_valueConstant1)->setText(KCalcConstMenu::Constants[option].value); + + (tmp_const->kcfg_nameConstant1)->setText(KCalcConstMenu::Constants[option].label); +} + +void KCalculator::slotChooseScientificConst2(int option) +{ + (tmp_const->kcfg_valueConstant2)->setText(KCalcConstMenu::Constants[option].value); + + (tmp_const->kcfg_nameConstant2)->setText(KCalcConstMenu::Constants[option].label); +} + +void KCalculator::slotChooseScientificConst3(int option) +{ + (tmp_const->kcfg_valueConstant3)->setText(KCalcConstMenu::Constants[option].value); + + (tmp_const->kcfg_nameConstant3)->setText(KCalcConstMenu::Constants[option].label); +} + +void KCalculator::slotChooseScientificConst4(int option) +{ + (tmp_const->kcfg_valueConstant4)->setText(KCalcConstMenu::Constants[option].value); + + (tmp_const->kcfg_nameConstant4)->setText(KCalcConstMenu::Constants[option].label); +} + +void KCalculator::slotChooseScientificConst5(int option) +{ + (tmp_const->kcfg_valueConstant5)->setText(KCalcConstMenu::Constants[option].value); + + (tmp_const->kcfg_nameConstant5)->setText(KCalcConstMenu::Constants[option].label); +} + + +void KCalculator::slotStatshow(bool toggled) +{ + if(toggled) + { + pbStat["NumData"]->show(); + pbStat["Mean"]->show(); + pbStat["StandardDeviation"]->show(); + pbStat["Median"]->show(); + pbStat["InputData"]->show(); + pbStat["ClearData"]->show(); + } + else + { + pbStat["NumData"]->hide(); + pbStat["Mean"]->hide(); + pbStat["StandardDeviation"]->hide(); + pbStat["Median"]->hide(); + pbStat["InputData"]->hide(); + pbStat["ClearData"]->hide(); + } + adjustSize(); + setFixedSize(sizeHint()); + KCalcSettings::setShowStat(toggled); +} + +void KCalculator::slotScientificshow(bool toggled) +{ + if(toggled) + { + pbScientific["HypMode"]->show(); + pbScientific["Sine"]->show(); + pbScientific["Cosine"]->show(); + pbScientific["Tangent"]->show(); + pbScientific["Log10"]->show(); + pbScientific["LogNatural"]->show(); + pbAngleChoose->show(); + if(!statusBar()->hasItem(2)) + statusBar()->insertFixedItem(" DEG ", 2, true); + statusBar()->setItemAlignment(2, AlignCenter); + calc_display->setStatusText(2, "Deg"); + slotAngleSelected(0); + } + else + { + pbScientific["HypMode"]->hide(); + pbScientific["Sine"]->hide(); + pbScientific["Cosine"]->hide(); + pbScientific["Tangent"]->hide(); + pbScientific["Log10"]->hide(); + pbScientific["LogNatural"]->hide(); + pbAngleChoose->hide(); + if(statusBar()->hasItem(2)) + statusBar()->removeItem(2); + calc_display->setStatusText(2, QString::null); + } + adjustSize(); + setFixedSize(sizeHint()); + KCalcSettings::setShowScientific(toggled); +} + +void KCalculator::slotLogicshow(bool toggled) +{ + if(toggled) + { + pbLogic["AND"]->show(); + pbLogic["OR"]->show(); + pbLogic["XOR"]->show(); + pbLogic["One-Complement"]->show(); + pbLogic["LeftShift"]->show(); + pbLogic["RightShift"]->show(); + if(!statusBar()->hasItem(1)) + statusBar()->insertFixedItem(" HEX ", 1, true); + statusBar()->setItemAlignment(1, AlignCenter); + calc_display->setStatusText(1, "Hex"); + resetBase(); + BaseChooseGroup->show(); + for (int i=10; i<16; i++) + (NumButtonGroup->find(i))->show(); + } + else + { + pbLogic["AND"]->hide(); + pbLogic["OR"]->hide(); + pbLogic["XOR"]->hide(); + pbLogic["One-Complement"]->hide(); + pbLogic["LeftShift"]->hide(); + pbLogic["RightShift"]->hide(); + // Hide Hex-Buttons, but first switch back to decimal + resetBase(); + BaseChooseGroup->hide(); + if(statusBar()->hasItem(1)) + statusBar()->removeItem(1); + calc_display->setStatusText(1, QString::null); + for (int i=10; i<16; i++) + (NumButtonGroup->find(i))->hide(); + } + adjustSize(); + setFixedSize(sizeHint()); + KCalcSettings::setShowLogic(toggled); +} + +void KCalculator::slotConstantsShow(bool toggled) +{ + if(toggled) + { + pbConstant[0]->show(); + pbConstant[1]->show(); + pbConstant[2]->show(); + pbConstant[3]->show(); + pbConstant[4]->show(); + pbConstant[5]->show(); + + } + else + { + pbConstant[0]->hide(); + pbConstant[1]->hide(); + pbConstant[2]->hide(); + pbConstant[3]->hide(); + pbConstant[4]->hide(); + pbConstant[5]->hide(); + } + adjustSize(); + setFixedSize(sizeHint()); + KCalcSettings::setShowConstants(toggled); +} + +// 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() +{ + pbConstant[0]->setLabelAndTooltip(); + pbConstant[1]->setLabelAndTooltip(); + pbConstant[2]->setLabelAndTooltip(); + pbConstant[3]->setLabelAndTooltip(); + pbConstant[4]->setLabelAndTooltip(); + pbConstant[5]->setLabelAndTooltip(); +} + +void KCalculator::slotShowAll(void) +{ + // I wonder why "setChecked" does not emit "toggled" + if(!actionStatshow->isChecked()) actionStatshow->activate(); + if(!actionScientificshow->isChecked()) actionScientificshow->activate(); + if(!actionLogicshow->isChecked()) actionLogicshow->activate(); + if(!actionConstantsShow->isChecked()) actionConstantsShow->activate(); +} + +void KCalculator::slotHideAll(void) +{ + // I wonder why "setChecked" does not emit "toggled" + if(actionStatshow->isChecked()) actionStatshow->activate(); + if(actionScientificshow->isChecked()) actionScientificshow->activate(); + if(actionLogicshow->isChecked()) actionLogicshow->activate(); + if(actionConstantsShow->isChecked()) actionConstantsShow->activate(); +} + +void KCalculator::updateSettings() +{ + changeButtonNames(); + set_colors(); + set_precision(); + // Show the result in the app's caption in taskbar (wishlist - bug #52858) + disconnect(calc_display, SIGNAL(changedText(const QString &)), + this, 0); + if (KCalcSettings::captionResult()) + { + connect(calc_display, + SIGNAL(changedText(const QString &)), + SLOT(setCaption(const QString &))); + } + else + { + setCaption(QString::null); + } + calc_display->changeSettings(); + + updateGeometry(); + resize(minimumSize()); + + // + // 1999-10-31 Espen Sand: Don't ask me why ;) + // + kapp->processOneEvent(); + setFixedHeight(minimumHeight()); +} + +void KCalculator::UpdateDisplay(bool get_amount_from_core, + bool store_result_in_history) +{ + if(get_amount_from_core) + { + calc_display->update_from_core(core, store_result_in_history); + } + else + { + calc_display->update(); + } + + pbInv->setOn(false); + +} + +void KCalculator::set_colors() +{ + QPushButton *p = NULL; + + calc_display->changeSettings(); + + QColor bg = palette().active().background(); + + QPalette numPal(KCalcSettings::numberButtonsColor(), bg); + for(int i=0; i<10; i++) + { + (NumButtonGroup->find(i))->setPalette(numPal); + } + + QPalette funcPal(KCalcSettings::functionButtonsColor(), bg); + for(p = mFunctionButtonList.first(); p; + p=mFunctionButtonList.next()) + { + p->setPalette(funcPal); + } + + QPalette statPal(KCalcSettings::statButtonsColor(), bg); + for(p = mStatButtonList.first(); p; p=mStatButtonList.next()) + { + p->setPalette(statPal); + } + + QPalette hexPal(KCalcSettings::hexButtonsColor(), bg); + for(int i=10; i<16; i++) + { + (NumButtonGroup->find(i))->setPalette(hexPal); + } + + QPalette memPal(KCalcSettings::memoryButtonsColor(), bg); + for(p = mMemButtonList.first(); p; p=mMemButtonList.next()) + { + p->setPalette(memPal); + } + + QPalette opPal(KCalcSettings::operationButtonsColor(), bg); + for(p = mOperationButtonList.first(); p; + p=mOperationButtonList.next()) + { + p->setPalette(opPal); + } +} + +void KCalculator::set_precision() +{ + KNumber:: setDefaultFloatPrecision(KCalcSettings::precision()); + UpdateDisplay(false); +} + +bool KCalculator::eventFilter(QObject *o, QEvent *e) +{ + if(e->type() == QEvent::DragEnter) + { + QDragEnterEvent *ev = (QDragEnterEvent *)e; + ev->accept(KColorDrag::canDecode(ev)); + return true; + } + else if(e->type() == QEvent::DragLeave) + { + return true; + } + else if(e->type() == QEvent::Drop) + { + if(!o->isA("KCalcButton")) + return false; + + QColor c; + QDropEvent *ev = (QDropEvent *)e; + if( KColorDrag::decode(ev, c)) + { + QPtrList<KCalcButton> *list; + int num_but; + if((num_but = NumButtonGroup->id((KCalcButton*)o)) + != -1) + { + QPalette pal(c, palette().active().background()); + + // Was it hex-button or normal digit?? + if (num_but <10) + for(int i=0; i<10; i++) + (NumButtonGroup->find(i))->setPalette(pal); + else + for(int i=10; i<16; i++) + (NumButtonGroup->find(i))->setPalette(pal); + + return true; + } + else if( mFunctionButtonList.findRef((KCalcButton*)o) != -1) + { + list = &mFunctionButtonList; + } + else if( mStatButtonList.findRef((KCalcButton*)o) != -1) + { + list = &mStatButtonList; + } + else if( mMemButtonList.findRef((KCalcButton*)o) != -1) + { + list = &mMemButtonList; + } + else if( mOperationButtonList.findRef((KCalcButton*)o) != -1) + { + list = &mOperationButtonList; + } + else + return false; + + QPalette pal(c, palette().active().background()); + + for(KCalcButton *p = list->first(); p; p=list->next()) + p->setPalette(pal); + } + + return true; + } + else + { + return KMainWindow::eventFilter(o, e); + } +} + + + + +//////////////////////////////////////////////////////////////// +// Include the meta-object code for classes in this file +// + +#include "kcalc.moc" + + +extern "C" KDE_EXPORT int kdemain(int argc, char *argv[]) +{ + KAboutData aboutData( "kcalc", I18N_NOOP("KCalc"), + version, description, KAboutData::License_GPL, + I18N_NOOP("(c) 2003-2005, Klaus Niederkr" "\xc3\xbc" "ger\n" + "(c) 1996-2000, Bernd Johannes Wuebben\n" + "(c) 2000-2005, The KDE Team")); + + /* Klaus Niederkrueger */ + aboutData.addAuthor("Klaus Niederkr" "\xc3\xbc" "ger", 0, "kniederk@math.uni-koeln.de"); + aboutData.addAuthor("Bernd Johannes Wuebben", 0, "wuebben@kde.org"); + aboutData.addAuthor("Evan Teran", 0, "eteran@alum.rit.edu"); + aboutData.addAuthor("Espen Sand", 0, "espen@kde.org"); + aboutData.addAuthor("Chris Howells", 0, "howells@kde.org"); + aboutData.addAuthor("Aaron J. Seigo", 0, "aseigo@olympusproject.org"); + aboutData.addAuthor("Charles Samuels", 0, "charles@altair.dhs.org"); + /* Rene Merou */ + aboutData.addAuthor("Ren" "\xc3\xa9" " M" "\xc3\xa9" "rou", 0, "ochominutosdearco@yahoo.es"); + KCmdLineArgs::init(argc, argv, &aboutData); + + KApplication app; +#if 0 + app->enableSessionManagement(true); + app->setWmCommand(argv[0]); +#endif + + KCalculator *calc = new KCalculator; + app.setTopWidget(calc); + calc->setCaption(QString::null); + calc->show(); + + int exitCode = app.exec(); + + return(exitCode); +} + diff --git a/kcalc/kcalc.desktop b/kcalc/kcalc.desktop new file mode 100644 index 0000000..19ae663 --- /dev/null +++ b/kcalc/kcalc.desktop @@ -0,0 +1,88 @@ +[Desktop Entry] +Name=KCalc +Name[af]=Kcalc +Name[ar]=Řاسب؊ Ů +Name[eo]=Kalkulilo +Name[hi]=ŕ¤ŕĽ-ŕ¤ŕĽŕ¤˛ŕĽŕ¤ +Name[lv]=KKalk +Name[ne]=ŕ¤ŕĽŕ¤ĄŕĽŕ¤ ŕ¤ŕĽŕ¤Żŕ¤žŕ¤˛ŕĽŕ¤ +Name[pa]=ŕ¨ŕŠŕ¨šŕ¨żŕ¨¸ŕ¨žŕ¨ŹŕŠ +Name[pl]=Kalkulator +Name[sv]=Kcalc +Name[ta]=ŕŽŕŻŕŽŕŽŁŕŽżŕŽŞŕŻŕŽŞŕŽžŕŽŠŕŻ +Name[tg]=KĐĐžŃинаи ҳиŃОйкŃнак +Name[th]=ŕšŕ¸ŕ¸Łŕ¸ˇŕšŕ¸ŕ¸ŕ¸ŕ¸´ŕ¸ŕšŕ¸Ľŕ¸ +Name[uz]=Kalkulyator +Name[uz@cyrillic]=ĐаНкŃĐťŃŃĐžŃ +Name[zh_TW]=KDE č¨çŽćŠ +Exec=kcalc -caption "%c" %i %m +Icon=kcalc +DocPath=kcalc/index.html +GenericName=Scientific Calculator +GenericName[af]=Wetenskaplike Sakrekenaar +GenericName[ar]=آŮŘŠ Řاسب؊ ŘšŮŮ
ŮŘŠ +GenericName[bg]=ĐаНкŃНаŃĐžŃ +GenericName[br]=Ur jederez skiantel +GenericName[bs]=Znanstveni kalkulator +GenericName[ca]=Calculadora cientĂfica +GenericName[cs]=VÄdeckĂĄ kalkulaÄka +GenericName[cy]=Cyfrifydd Gwyddonol +GenericName[da]=Videnskabelig regnemaskine +GenericName[de]=Wissenschaftlicher Taschenrechner +GenericName[el]=ÎĎΚĎĎÎˇÎźÎżÎ˝ÎšÎşĎ ÎşÎżÎźĎΚοĎ
ĎÎľĎΏκΚ +GenericName[eo]=Scienca kalkulilo +GenericName[es]=Calculadora cientĂfica +GenericName[et]=Teaduslik kalkulaator +GenericName[eu]=Kalkulagailu Zientifikoa +GenericName[fa]=Ů
اشŰŮ Řساب ŘšŮŮ
Ű +GenericName[fi]=Tieteellinen laskin +GenericName[fr]=Une calculatrice scientifique +GenericName[ga]=ĂireamhĂĄn EolaĂochta +GenericName[he]=××׊××× ×××˘× +GenericName[hi]=ाŕĽŕ¤ŕĽŕ¤ŕ¤žŕ¤¨ŕ¤żŕ¤ ŕ¤ŕ¤Łŕ¤ +GenericName[hr]=Znanstveni kalkulator +GenericName[hu]=SzĂĄmolĂłgĂŠp +GenericName[is]=Ăflug reiknivĂŠl +GenericName[it]=Calcolatrice scientifica +GenericName[ja]=ç§ĺŚéťĺ +GenericName[ka]=áááŞáááá áŁáá áááááŁááá˘áá á +GenericName[kk]=ŇŃĐťŃПи каНŃĐşŃĐťŃŃĐžŃ +GenericName[km]=áááśááá¸áâááˇáâáááâááˇááááśááśááááá +GenericName[lt]=Mokslinis skaiÄiuotuvas +GenericName[lv]=ZinÄtnisks Kalkulators +GenericName[mk]=ĐĐ°ŃŃон каНкŃНаŃĐžŃ +GenericName[mt]=KalkulatriÄi xjentifika +GenericName[nb]=Vitenskaplig kalkulator +GenericName[nds]=Wetenschaplich Taschenreekner +GenericName[ne]=ाŕĽŕ¤ŕĽŕ¤ŕ¤žŕ¤¨ŕ¤żŕ¤ ŕ¤ŕ¤Łŕ¤ŕ¤Żŕ¤¨ŕĽŕ¤¤ŕĽŕ¤° +GenericName[nl]=Wetenschappelijke rekenmachine +GenericName[nn]=Vitskapleg kalkulator +GenericName[pa]=ਾਿŕ¨ŕ¨żŕ¨ŕ¨¨ŕ¨żŕ¨ ਹਿਸਾਬ੠+GenericName[pl]=Kalkulator naukowy +GenericName[pt]=Calculadora Cientifica +GenericName[pt_BR]=Calculadora CientĂfica +GenericName[ro]=Calculator ĹtiinĹŁific +GenericName[ru]=ĐĐ°ĐťŃĐşŃĐťŃŃĐžŃ +GenericName[sk]=VedeckĂĄ kalkulaÄka +GenericName[sl]=Znanstveni kalkulator +GenericName[sr]=ĐĐ°ŃŃни каНкŃНаŃĐžŃ +GenericName[sr@Latn]=NauÄni kalkulator +GenericName[sv]=Vetenskaplig miniräknare +GenericName[ta]= ŕŽ
றிவியல௠ŕŽŕŽžŕŽ°ŕŻŕŽ¨ŕŻŕŽ¤ ŕŽŕŽŁŕŽżŕŽŞŕŻŕŽŞŕŽžŕŽŠŕŻ +GenericName[tg]=ĐĐžŃинаи ҳиŃОйкŃнаки ĐНПӣ +GenericName[th]=ŕšŕ¸ŕ¸Łŕ¸ˇŕšŕ¸ŕ¸ŕ¸ŕ¸´ŕ¸ŕšŕ¸Ľŕ¸ŕšŕ¸ŕ¸ŕ¸§ŕ¸´ŕ¸ŕ¸˘ŕ¸˛ŕ¸¨ŕ¸˛ŕ¸Şŕ¸ŕ¸Łŕš +GenericName[tr]=Bilimsel Hesap Makinesi +GenericName[uk]=ĐĐ°ĐťŃĐşŃĐťŃŃĐžŃ Đ´ĐťŃ Đ˝Đ°ŃкОвŃŃв +GenericName[uz]=Ilmiy kalkulyator +GenericName[uz@cyrillic]=ĐНПиК каНкŃĐťŃŃĐžŃ +GenericName[ven]=Khalikhuleitha ya tshisaintsi +GenericName[vi]=MĂĄy tĂnh khoa háťc +GenericName[wa]=Carculete syintifike +GenericName[xh]=Umatshini Wokubala Ezenzululwazi +GenericName[zh_CN]=ç§ĺŚčŽĄçŽĺ¨ +GenericName[zh_TW]=ç§ĺ¸č¨çŽćŠ +GenericName[zu]=Umshini wokubala ezenzululwazi +Terminal=false +Type=Application +X-KDE-StartupNotify=true +Categories=Qt;KDE;Utility;X-KDE-Utilities-Desktop; diff --git a/kcalc/kcalc.h b/kcalc/kcalc.h new file mode 100644 index 0000000..0ede211 --- /dev/null +++ b/kcalc/kcalc.h @@ -0,0 +1,239 @@ +/* + KCalc, a scientific calculator for the X window system using the + Qt widget libraries, available at no cost at http://www.troll.no + + Copyright (C) 1996 Bernd Johannes Wuebben + wuebben@math.cornell.edu + + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef KCALC_H +#define KCALC_H + +class QPushButton; +class QRadioButton; +class QButtonGroup; +class QHButtonGroup; +class QWidget; +class DispLogic; +class Constants; +#include <kmainwindow.h> + +/* + Kcalc basically consist of a class for the GUI (here), a class for + the display (dlabel.h), and one for the mathematics core + (kcalc_core.h). + + When for example '+' is pressed, one sends the contents of the + Display and the '+' to the core via "core.Plus(DISPLAY_AMOUNT)". + This only updates the core. To bring the changes to the display, + use afterwards "UpdateDisplay(true)". + + "UpdateDisplay(true)" means that the amount to be displayed should + be taken from the core (get the result of some operation that was + performed), "UpdateDisplay(false)" has already the information, what + to be display (e.g. user is typing in a number). Note that in the + last case the core does not know the number typed in until some + operation button is pressed, e.g. "core.Plus(display_number)". + */ + +#include "config.h" + +// IMPORTANT this has to come after ../config.h +#include "kcalc_core.h" +#include "kcalc_button.h" +#include "kcalc_const_button.h" + +class KCalculator : public KMainWindow +{ + Q_OBJECT + +public: + KCalculator(QWidget *parent = 0, const char *name = 0); + ~KCalculator(); + +signals: + void switchInverse(bool); + void switchMode(ButtonModeFlags,bool); + void switchShowAccels(bool); + +private: + virtual bool eventFilter( QObject *o, QEvent *e ); + void updateGeometry(); + void setupMainActions(void); + void setupStatusbar(void); + QWidget *setupNumericKeys(QWidget *parent); + void setupLogicKeys(QWidget *parent); + void setupScientificKeys(QWidget *parent); + void setupStatisticKeys(QWidget *parent); + void setupConstantsKeys(QWidget *parent); + void keyPressEvent(QKeyEvent *e); + void keyReleaseEvent(QKeyEvent *e); + void set_precision(); + void set_style(); + void resetBase(void) { (BaseChooseGroup->find(1))->animateClick();}; + + void UpdateDisplay(bool get_amount_from_core = false, + bool store_result_in_history = false); + +protected slots: + void changeButtonNames(); + void updateSettings(); + void set_colors(); + void EnterEqual(); + void showSettings(); + void slotStatshow(bool toggled); + void slotScientificshow(bool toggled); + void slotLogicshow(bool toggled); + void slotConstantsShow(bool toggled); + void slotShowAll(void); + void slotHideAll(void); + void slotAngleSelected(int number); + void slotBaseSelected(int number); + void slotNumberclicked(int number_clicked); + void slotEEclicked(void); + void slotInvtoggled(bool myboolean); + void slotMemRecallclicked(void); + void slotMemStoreclicked(void); + void slotSinclicked(void); + void slotPlusMinusclicked(void); + void slotMemPlusMinusclicked(void); + void slotCosclicked(void); + void slotReciclicked(void); + void slotTanclicked(void); + void slotFactorialclicked(void); + void slotLogclicked(void); + void slotSquareclicked(void); + void slotLnclicked(void); + void slotPowerclicked(void); + void slotMCclicked(void); + void slotClearclicked(void); + void slotACclicked(void); + void slotParenOpenclicked(void); + void slotParenCloseclicked(void); + void slotANDclicked(void); + void slotXclicked(void); + void slotDivisionclicked(void); + void slotORclicked(void); + void slotXORclicked(void); + void slotPlusclicked(void); + void slotMinusclicked(void); + void slotLeftShiftclicked(void); + void slotRightShiftclicked(void); + void slotPeriodclicked(void); + void slotEqualclicked(void); + void slotPercentclicked(void); + void slotRootclicked(void); + void slotNegateclicked(void); + void slotModclicked(void); + void slotStatNumclicked(void); + void slotStatMeanclicked(void); + void slotStatStdDevclicked(void); + void slotStatMedianclicked(void); + void slotStatDataInputclicked(void); + void slotStatClearDataclicked(void); + void slotHyptoggled(bool flag); + void slotConstclicked(int); + + void slotConstantToDisplay(int constant); + void slotChooseScientificConst0(int option); + void slotChooseScientificConst1(int option); + void slotChooseScientificConst2(int option); + void slotChooseScientificConst3(int option); + void slotChooseScientificConst4(int option); + void slotChooseScientificConst5(int option); + +private: + bool inverse; + bool hyp_mode; + KNumber memory_num; + KNumber setvalue; + + // angle modes for trigonometric values + enum { + DegMode, + RadMode, + GradMode + } _angle_mode; + + +private: + QWidget *mSmallPage; + QWidget *mLargePage; + QWidget *mNumericPage; + + DispLogic* calc_display; // for historic reasons in "dlabel.h" + QRadioButton* pbBaseChoose[4]; + QPushButton* pbAngleChoose; + QDict<KCalcButton> pbStat; + QDict<KCalcButton> pbScientific; + QDict<KCalcButton> pbLogic; + KCalcConstButton* pbConstant[10]; + KCalcButton* pbAC; + KCalcButton* pbAND; + KCalcButton* pbClear; + KCalcButton* pbDivision; + KCalcButton* pbEE; + KCalcButton* pbEqual; + KCalcButton* pbFactorial; + KCalcButton* pbInv; + KCalcButton* pbMC; + KCalcButton* pbMinus; + KCalcButton* pbMod; + KCalcButton* pbMemPlusMinus; + KCalcButton* pbMemRecall; + KCalcButton* pbMemStore; + KCalcButton* pbOR; + KCalcButton* pbParenClose; + KCalcButton* pbParenOpen; + KCalcButton* pbPercent; + KCalcButton* pbPeriod; + KCalcButton* pbPlus; + KCalcButton* pbPlusMinus; + KCalcButton* pbPower; + KCalcButton* pbReci; + KSquareButton* pbRoot; + KCalcButton* pbSquare; + KCalcButton* pbX; + KCalcButton* pbXOR; + + Constants * tmp_const; // this is the dialog for configuring const + // buttons would like to remove this, but + // don't know how + + QHButtonGroup* BaseChooseGroup; + // NumButtonGroup: 0-9 = digits, 0xA-0xF = hex-keys + QButtonGroup* NumButtonGroup; + // ConstButtonGroup C1-C6 + QButtonGroup* ConstButtonGroup; + + KToggleAction *actionStatshow; + KToggleAction *actionScientificshow; + KToggleAction *actionLogicshow; + KToggleAction *actionConstantsShow; + + QPtrList<KCalcButton> mFunctionButtonList; + QPtrList<KCalcButton> mStatButtonList; + QPtrList<KCalcButton> mMemButtonList; + QPtrList<KCalcButton> mOperationButtonList; + + int mInternalSpacing; + + CalcEngine core; +}; + +#endif // KCALC_H diff --git a/kcalc/kcalc.kcfg b/kcalc/kcalc.kcfg new file mode 100644 index 0000000..e4275b7 --- /dev/null +++ b/kcalc/kcalc.kcfg @@ -0,0 +1,127 @@ +<?xml version="1.0" encoding="UTF-8"?> +<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 + http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" > + <include>kapplication.h</include> + <include>kglobalsettings.h</include> + <include>config.h</include> + <kcfgfile name="kcalcrc"/> + <group name="Colors"> + <entry name="ForeColor" type="Color"> + <label>The foreground color of the display.</label> + <default>#000000</default> + </entry> + <entry name="BackColor" type="Color"> + <label>The background color of the display.</label> + <default>#BDFFB4</default> + </entry> + <entry name="NumberButtonsColor" type="Color"> + <label>The color of number buttons.</label> + <code>QColor defaultButtonColor = kapp->palette().active().background();</code> + <default code="true">defaultButtonColor</default> + </entry> + <entry name="FunctionButtonsColor" type="Color"> + <label>The color of function buttons.</label> + <default code="true">defaultButtonColor</default> + </entry> + <entry name="StatButtonsColor" type="Color"> + <label>The color of statistical buttons.</label> + <default code="true">defaultButtonColor</default> + </entry> + <entry name="HexButtonsColor" type="Color"> + <label>The color of hex buttons.</label> + <default code="true">defaultButtonColor</default> + </entry> + <entry name="MemoryButtonsColor" type="Color"> + <label>The color of memory buttons.</label> + <default code="true">defaultButtonColor</default> + </entry> + <entry name="OperationButtonsColor" type="Color"> + <label>The color of operation buttons.</label> + <default code="true">defaultButtonColor</default> + </entry> + </group> + <group name="Font"> + <entry name="Font" type="Font"> + <label>The font to use in the display.</label> + <default code="true">QFont(KGlobalSettings::generalFont().family(), 14, QFont::Bold)</default> + </entry> + </group> + <group name="Precision"> + <entry name="Precision" type="UInt" key="precision"> + <label>Maximum number of digits displayed.</label> + <whatsthis> + KCalc can compute with many more digits than the number that + fits on the display. This setting gives the maximum number of + digits displayed, before KCalc starts using scientific notation, + i.e. notation of the type 2.34e12. + </whatsthis> + <default>12</default> + <min>8</min> + <max>200</max> + </entry> + <entry name="FixedPrecision" type="UInt" key="fixedprecision"> + <label>Number of fixed decimal digits.</label> + <default>2</default> + </entry> + <entry name="Fixed" type="Bool" key="fixed"> + <label>Whether to use fixed decimal places.</label> + <default>false</default> + </entry> + </group> + <group name="General"> + <entry name="Beep" type="Bool" key="beep"> + <label>Whether to beep on error.</label> + <default>true</default> + </entry> + <entry name="CaptionResult" type="Bool" key="captionresult"> + <label>Whether to show the result in the window title.</label> + <default>false</default> + </entry> + <entry name="GroupDigits" type="Bool" key="groupdigits"> + <label>Whether to group digits.</label> + <default>true</default> + </entry> + <entry name="ShowStat" type="Bool"> + <label>Whether to show statistical buttons.</label> + <default>false</default> + </entry> + <entry name="ShowScientific" type="Bool"> + <label>Whether to show buttons with functions used in science/engineering, + like exp, log, sin etc.</label> + <default>false</default> + </entry> + <entry name="ShowLogic" type="Bool"> + <label>Whether to show logic buttons.</label> + <default>false</default> + </entry> + <entry name="ShowConstants" type="Bool"> + <label>Whether to show constant buttons.</label> + <default>false</default> + </entry> + </group> + <group name="UserConstants"> + <entry name="nameConstant$(ConstIndex)" type="String" key="nameConstant$(ConstIndex)"> + <label>Name of the user programmable constants.</label> + <parameter name="ConstIndex" type="Int" max="5"/> + <default param="0">C1</default> + <default param="1">C2</default> + <default param="2">C3</default> + <default param="3">C4</default> + <default param="4">C5</default> + <default param="5">C6</default> + </entry> + + <entry name="valueConstant$(ConstIndex)" type="String" key="valueConstant$(ConstIndex)"> + <label>List of user programmable constants</label> + <parameter name="ConstIndex" type="Int" max="5"/> + <default param="0">0</default> + <default param="1">0</default> + <default param="2">0</default> + <default param="3">0</default> + <default param="4">0</default> + <default param="5">0</default> + </entry> + </group> +</kcfg> diff --git a/kcalc/kcalc_button.cpp b/kcalc/kcalc_button.cpp new file mode 100644 index 0000000..7021a1a --- /dev/null +++ b/kcalc/kcalc_button.cpp @@ -0,0 +1,168 @@ +/* + kCalculator, a simple scientific calculator for KDE + + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include <qsimplerichtext.h> +#include <qtooltip.h> +#include <qpainter.h> + + +#include "qdom.h" + +#include "kcalc_button.h" + + +KCalcButton::KCalcButton(QWidget * parent, const char * name) + : KPushButton(parent, name), _show_accel_mode(false), + _mode_flags(ModeNormal) +{ + setAutoDefault(false); +} + +KCalcButton::KCalcButton(const QString &label, QWidget * parent, + const char * name, const QString &tooltip) + : KPushButton(label, parent, name), _show_accel_mode(false), _mode_flags(ModeNormal) +{ + setAutoDefault(false); + addMode(ModeNormal, label, tooltip); +} + +void KCalcButton::addMode(ButtonModeFlags mode, QString label, QString tooltip, bool is_label_richtext) +{ + if (_mode.contains(mode)) _mode.remove(mode); + + _mode[mode] = ButtonMode(label, tooltip, is_label_richtext); + + // Need to put each button into default mode first + if(mode == ModeNormal) slotSetMode(ModeNormal, true); +} + +void KCalcButton::slotSetMode(ButtonModeFlags mode, bool flag) +{ + ButtonModeFlags new_mode; + + if (flag) { // if the specified mode is to be set (i.e. flag = true) + new_mode = ButtonModeFlags(_mode_flags | mode); + } else if (_mode_flags && mode) { // if the specified mode is to be cleared (i.e. flag = false) + new_mode = ButtonModeFlags(_mode_flags - mode); + } else { + return; // nothing to do + } + + if (_mode.contains(new_mode)) { + // save accel, because setting label erases accel + QKeySequence _accel = accel(); + + if(_mode[new_mode].is_label_richtext) + _label = _mode[new_mode].label; + else + setText(_mode[new_mode].label); + QToolTip::remove(this); + QToolTip::add(this, _mode[new_mode].tooltip); + _mode_flags = new_mode; + + // restore accel + setAccel(_accel); + } + + // this is necessary for people pressing CTRL and changing mode at + // the same time... + if (_show_accel_mode) slotSetAccelDisplayMode(true); + + update(); +} + +static QString escape(QString str) +{ + str.replace('&', "&&"); + return str; +} + + +void KCalcButton::slotSetAccelDisplayMode(bool flag) +{ + _show_accel_mode = flag; + + // save accel, because setting label erases accel + QKeySequence _accel = accel(); + + if (flag == true) { + setText(escape(QString(accel()))); + } else { + setText(_mode[_mode_flags].label); + } + + // restore accel + setAccel(_accel); +} + +void KCalcButton::paintLabel(QPainter *paint) +{ + if (_mode[_mode_flags].is_label_richtext) { + QSimpleRichText _text(_label, font()); + _text.draw(paint, width()/2-_text.width()/2, 0, childrenRegion(), colorGroup()); + } else { + KPushButton::drawButtonLabel(paint); + } +} + +void KCalcButton::drawButtonLabel(QPainter *paint) +{ + if (_show_accel_mode) { + KPushButton::drawButtonLabel(paint); + } else if (_mode.contains(_mode_flags)) { + paintLabel(paint); + } +} + + +void KSquareButton::paintLabel(QPainter *paint) +{ + int w = width(); + int w2 = w/2 - 13; + int h = height(); + int h2 = h/2 - 7; + // in some KDE-styles (.NET, Phase,...) we have to set the painter back to the right color + paint->setPen(foregroundColor()); + // these statements are for the improved + // representation of the sqrt function + paint->drawLine(w2, 11 + h2, w2 + 2, 7 + h2); + paint->drawLine(w2 + 2, 7 + h2, w2 + 4, 14 + h2); + paint->drawLine(w2 + 4, 14 + h2, w2 + 6, 1 + h2); + paint->drawLine(w2 + 6, 1 + h2, w2 + 27, 1 + h2); + paint->drawLine(w2 + 27, 1 + h2, w2 + 27, 4 + h2); + // add a three for the cube root + if (_mode_flags & ModeInverse) { + paint->drawText(w2-2, 9 + h2, "ł"); + } +} + +void KSquareButton::drawButtonLabel(QPainter *paint) +{ + if (_show_accel_mode) { + KPushButton::drawButtonLabel(paint); + } else if (_mode.contains(_mode_flags)) { + paintLabel(paint); + } +} + +#include "kcalc_button.moc" + diff --git a/kcalc/kcalc_button.h b/kcalc/kcalc_button.h new file mode 100644 index 0000000..0998b5f --- /dev/null +++ b/kcalc/kcalc_button.h @@ -0,0 +1,105 @@ +/* + KCalc, a scientific calculator for the X window system using the + Qt widget libraries, available at no cost at http://www.troll.no + + Copyright (C) 1996 Bernd Johannes Wuebben + wuebben@math.cornell.edu + + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef _KCALC_BUTTON_H +#define _KCALC_BUTTON_H + +#include <kpushbutton.h> + +// The class KCalcButton is an overriden KPushButton. It offers extra +// functionality e.g. labels can be richtext or the accels can be +// shown in the label, but the most important thing is that the button +// may have several modes with corresponding labels. When one switches +// modes, the corresponding label is displayed. + + +enum ButtonModeFlags {ModeNormal = 0, ModeInverse = 1, ModeHyperbolic = 2}; + +class QDomNode; + +// Each kcalc button can be in one of several modes. +// The following class describes label, tooltip etc. for each mode... +class ButtonMode +{ +public: + ButtonMode(void) {}; + ButtonMode(QString &label, QString &tooltip, bool is_label_richtext) + : is_label_richtext(is_label_richtext), tooltip(tooltip) + { + if (is_label_richtext) + this->label = "<qt type=\"page\"><center>" + label + "</center></qt>"; + else + this->label = label; + }; + + QString label; + bool is_label_richtext; + QString tooltip; +}; + + +class KCalcButton : public KPushButton +{ +Q_OBJECT + +public: + KCalcButton(QWidget *parent, const char * name = 0); + KCalcButton(const QString &label, QWidget *parent, const char * name = 0, + const QString &tooltip = QString()); + + void addMode(ButtonModeFlags mode, QString label, QString tooltip, bool is_label_richtext = false); + +public slots: + void slotSetMode(ButtonModeFlags mode, bool flag); + void slotSetAccelDisplayMode(bool flag); + +protected: + virtual void drawButtonLabel(QPainter *paint); + void paintLabel(QPainter *paint); + +protected: + bool _show_accel_mode; + QString _label; + + ButtonModeFlags _mode_flags; + + QMap<ButtonModeFlags, ButtonMode> _mode; +}; + +class KSquareButton : public KCalcButton +{ +Q_OBJECT + +public: + KSquareButton(QWidget *parent, const char * name = 0) + : KCalcButton(parent, name) { }; + KSquareButton(const QString &label, QWidget *parent, const char * name = 0, + const QString &tooltip = QString()) + : KCalcButton(label, parent, name, tooltip) { }; + +protected: + virtual void drawButtonLabel(QPainter *paint); + void paintLabel(QPainter *paint); +}; + +#endif // _KCALC_BUTTON_H diff --git a/kcalc/kcalc_const_button.cpp b/kcalc/kcalc_const_button.cpp new file mode 100644 index 0000000..e9c4216 --- /dev/null +++ b/kcalc/kcalc_const_button.cpp @@ -0,0 +1,109 @@ +/* + kCalculator, a simple scientific calculator for KDE + + Copyright (C) 2003 Klaus Niederkrueger <kniederk@math.uni-koeln.de> + + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include <qstring.h> + + +#include <kcmenumngr.h> +#include <kinputdialog.h> +#include <kpopupmenu.h> + +#include "kcalc_const_button.h" +#include "kcalc_const_menu.h" +#include "kcalc_settings.h" + + +KCalcConstButton::KCalcConstButton(QWidget *parent, int but_num, const char * name) + : KCalcButton(parent, name), _button_num(but_num) +{ + addMode(ModeInverse, "Store", i18n("Write display data into memory")); + + initPopupMenu(); +} + + +KCalcConstButton::KCalcConstButton(const QString &label, QWidget *parent, int but_num, + const char * name, const QString &tooltip) + : KCalcButton(label, parent, name, tooltip), _button_num(but_num) +{ + addMode(ModeInverse, "Store", i18n("Write display data into memory")); + + initPopupMenu(); +} + +QString KCalcConstButton::constant(void) const +{ + return KCalcSettings::valueConstant(_button_num); +} + +void KCalcConstButton::setLabelAndTooltip(void) +{ + QString new_label = QString("C") + QString().setNum(_button_num + 1); + QString new_tooltip; + + new_label = (KCalcSettings::nameConstant(_button_num).isNull() ? new_label : KCalcSettings::nameConstant(_button_num)); + + new_tooltip = new_label + "=" + KCalcSettings::valueConstant(_button_num); + + addMode(ModeNormal, new_label, new_tooltip); +} + +void KCalcConstButton::initPopupMenu(void) +{ + KCalcConstMenu *tmp_menu = new KCalcConstMenu(this); + + _popup = new KPopupMenu(this, "set const-cutton"); + _popup->insertItem(i18n("Set Name"), 0); + _popup->insertItem(i18n("Choose From List"), tmp_menu, 1); + + connect(_popup, SIGNAL(activated(int)), SLOT(slotConfigureButton(int))); + connect(tmp_menu, SIGNAL(activated(int)), SLOT(slotChooseScientificConst(int))); + + KContextMenuManager::insert(this, _popup); +} + +void KCalcConstButton::slotConfigureButton(int option) +{ + if (option == 0) + { + bool yes_no; + QString input = KInputDialog::text(i18n("New Name for Constant"), i18n("New name:"), + text(), &yes_no, this, "nameUserConstants-Dialog"); + if(yes_no) { + KCalcSettings::setNameConstant(_button_num, input); + setLabelAndTooltip(); + } + } +} + +void KCalcConstButton::slotChooseScientificConst(int option) +{ + KCalcSettings::setValueConstant(_button_num, + KCalcConstMenu::Constants[option].value); + + KCalcSettings::setNameConstant(_button_num, + KCalcConstMenu::Constants[option].label); + + setLabelAndTooltip(); +} + +#include "kcalc_const_button.moc" + diff --git a/kcalc/kcalc_const_button.h b/kcalc/kcalc_const_button.h new file mode 100644 index 0000000..18ebf3e --- /dev/null +++ b/kcalc/kcalc_const_button.h @@ -0,0 +1,58 @@ +/* + KCalc, a scientific calculator for the X window system using the + Qt widget libraries, available at no cost at http://www.troll.no + + Copyright (C) 1996 Bernd Johannes Wuebben + wuebben@math.cornell.edu + + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef _KCALC_CONST_BUTTON_H +#define _KCALC_CONST_BUTTON_H + +#include <klocale.h> +#include "kcalc_button.h" + + +class KCalcConstButton : public KCalcButton +{ +Q_OBJECT + + public: + + KCalcConstButton(QWidget *parent, int but_num, const char * name = 0); + + KCalcConstButton(const QString &label, QWidget *parent, int but_num, const char * name = 0, + const QString &tooltip = QString()); + + QString constant(void) const; + + void setLabelAndTooltip(void); + + private slots: + void slotConfigureButton(int option); + void slotChooseScientificConst(int option); + + private: + void initPopupMenu(void); + + KPopupMenu* _popup; + int _button_num; +}; + + +#endif // _KCALC_CONST_BUTTON_H diff --git a/kcalc/kcalc_const_menu.cpp b/kcalc/kcalc_const_menu.cpp new file mode 100644 index 0000000..77bb02e --- /dev/null +++ b/kcalc/kcalc_const_menu.cpp @@ -0,0 +1,89 @@ +/* + kCalculator, a simple scientific calculator for KDE + + Copyright (C) 2003 Klaus Niederkrueger <kniederk@math.uni-koeln.de> + + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include <klocale.h> + +#include "kcalc_const_menu.h" + +#define NUM_CONST 17 + +const struct science_constant KCalcConstMenu::Constants[] = { + {QString::fromUtf8("Ď"), I18N_NOOP("Pi"), "", + "3.1415926535897932384626433832795028841971693993751" + "05820974944592307816406286208998628034825342117068", Mathematics}, + {"e", I18N_NOOP("Euler Number"), "", + "2.7182818284590452353602874713526624977572470936999" + "59574966967627724076630353547594571382178525166427", Mathematics}, + {QString::fromUtf8("Ď"), I18N_NOOP("Golden Ratio"), "", "1.61803398874989484820458683436563811", Mathematics}, + {"c", I18N_NOOP("Light Speed"), "", "2.99792458e8", Electromagnetic}, + {"h", I18N_NOOP("Planck's Constant"), "", "6.6260693e-34", Nuclear}, + {"G", I18N_NOOP("Constant of Gravitation"), "", "6.6742e-11", Gravitation}, + {"g", I18N_NOOP("Earth Acceleration"), "", "9.80665", Gravitation}, + {"e", I18N_NOOP("Elementary Charge"), "", "1.60217653e-19", ConstantCategory(Electromagnetic|Nuclear)}, + {"Z_0", I18N_NOOP("Impedance of Vacuum"), "", "376.730313461", Electromagnetic}, + {QString::fromUtf8("Îą"), I18N_NOOP("Fine-Structure Constant"), "", "7.297352568e-3", Nuclear}, + {QString::fromUtf8("Îź")+"_0", I18N_NOOP("Permeability of Vacuum"), "", "1.2566370614e-6", Electromagnetic}, + {QString::fromUtf8("Îľ")+"_0", I18N_NOOP("Permittivity of vacuum"), "", "8.854187817e-12", Electromagnetic}, + {"k", I18N_NOOP("Boltzmann Constant"), "", "1.3806505e-23", Thermodynamics}, + {"1u", I18N_NOOP("Atomic Mass Unit"), "", "1.66053886e-27", Thermodynamics}, + {"R", I18N_NOOP("Molar Gas Constant"), "", "8.314472", Thermodynamics}, + {QString::fromUtf8("Ď"), I18N_NOOP("Stefan-Boltzmann Constant"), "", "5.670400e-8", Thermodynamics}, + {"N_A", I18N_NOOP("Avogadro's Number"), "", "6.0221415e23", Thermodynamics} +}; + +KCalcConstMenu::KCalcConstMenu(QWidget * parent, const char * name) + : QPopupMenu(parent, name) +{ + QPopupMenu *math_menu = new QPopupMenu(this, "mathematical constants"); + QPopupMenu *em_menu = new QPopupMenu(this, "electromagnetic constants"); + QPopupMenu *nuclear_menu = new QPopupMenu(this, "nuclear constants"); + QPopupMenu *thermo_menu = new QPopupMenu(this, "thermodynamics constants"); + QPopupMenu *gravitation_menu = new QPopupMenu(this, "gravitation constants"); + + insertItem(i18n("Mathematics"), math_menu); + insertItem(i18n("Electromagnetism"), em_menu); + insertItem(i18n("Atomic && Nuclear"), nuclear_menu); + insertItem(i18n("Thermodynamics"), thermo_menu); + insertItem(i18n("Gravitation"), gravitation_menu); + + connect(math_menu, SIGNAL(activated(int)), this, SLOT(slotPassActivate(int))); + connect(em_menu, SIGNAL(activated(int)), this, SLOT(slotPassActivate(int))); + connect(nuclear_menu, SIGNAL(activated(int)), this, SLOT(slotPassActivate(int))); + connect(thermo_menu, SIGNAL(activated(int)), this, SLOT(slotPassActivate(int))); + connect(gravitation_menu, SIGNAL(activated(int)), this, SLOT(slotPassActivate(int))); + + + for (int i = 0; i<NUM_CONST; i++) { + if(Constants[i].category & Mathematics) + math_menu->insertItem(i18n(Constants[i].name), i); + if(Constants[i].category & Electromagnetic) + em_menu->insertItem(i18n(Constants[i].name), i); + if(Constants[i].category & Nuclear) + nuclear_menu->insertItem(i18n(Constants[i].name), i); + if(Constants[i].category & Thermodynamics) + thermo_menu->insertItem(i18n(Constants[i].name), i); + if(Constants[i].category & Gravitation) + gravitation_menu->insertItem(i18n(Constants[i].name), i); + } +} + + +#include "kcalc_const_menu.moc" diff --git a/kcalc/kcalc_const_menu.h b/kcalc/kcalc_const_menu.h new file mode 100644 index 0000000..4ae8da3 --- /dev/null +++ b/kcalc/kcalc_const_menu.h @@ -0,0 +1,55 @@ +/* + KCalc, a scientific calculator for the X window system using the + Qt widget libraries, available at no cost at http://www.troll.no + + Copyright (C) 2004 Klaus Niederkruger + + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef _KCALC_CONST_MENU_H +#define _KCALC_CONST_MENU_H + +#include <qpopupmenu.h> +#include <qstring.h> + +enum ConstantCategory {Mathematics = 1, Electromagnetic = 2, Nuclear = 4, Thermodynamics = 8, Gravitation = 16}; + +struct science_constant{ + QString label; + const char * name; + QString whatsthis; + QString value; + ConstantCategory category; +}; + +class KCalcConstMenu : public QPopupMenu +{ +Q_OBJECT + + public: + KCalcConstMenu(QWidget * parent = 0, const char * name = 0); + + static const struct science_constant Constants[]; + +public slots: + void slotPassActivate(int item) + { + emit activated(item); + }; +}; + +#endif // _KCALC_CONST_MENU_H diff --git a/kcalc/kcalc_core.cpp b/kcalc/kcalc_core.cpp new file mode 100644 index 0000000..4270895 --- /dev/null +++ b/kcalc/kcalc_core.cpp @@ -0,0 +1,1004 @@ +/* + kCalculator, a scientific calculator for the X window system using the + Qt widget libraries, available at no cost at http://www.troll.no + + The stack engine contained in this file was take from + Martin Bartlett's xfrmcalc + + portions: Copyright (C) 2003-2006 Klaus Niederkrueger + + portions: Copyright (C) 1996 Bernd Johannes Wuebben + wuebben@math.cornell.edu + + portions: Copyright (C) 1995 Martin Bartlett + + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + + +#if defined(_ISOC99_SOURCE) + #include <cassert> + #include <cstdio> + #include <climits> + #include <csignal> + #include <cerrno> + #include <cstring> + using namespace std; +#else + #include <limits.h> + #include <stdio.h> + #include <assert.h> + #include <signal.h> + #include <errno.h> + #include <string.h> +#endif + +#include <config.h> +#include "kcalc_core.h" +#include <stdlib.h> +#include <klocale.h> +#include <kmessagebox.h> +#include "kcalctype.h" + +#ifndef HAVE_FUNC_ISINF + #ifdef HAVE_IEEEFP_H + #include <ieeefp.h> + #else + #include <math.h> + #endif + +#undef isinf +int isinf(double x) +{ +#ifdef _HPUX_SOURCE +return !isfinite(x) && x == x; +#else +return !finite(x) && x==x; +#endif +} + +#endif + + +static void fpe_handler(int fpe_parm) +{ + UNUSED(fpe_parm); + // display_error = true; + //tmp_number = 0L; +} + + +static bool _error; + +static KNumber ExecOr(const KNumber & left_op, const KNumber & right_op) +{ + return (left_op | right_op); +} + +static KNumber ExecXor(const KNumber & left_op, const KNumber & right_op) +{ + return (left_op | right_op) - (left_op & right_op); +} + +static KNumber ExecAnd(const KNumber & left_op, const KNumber & right_op) +{ + return (left_op & right_op); +} + +static KNumber ExecLsh(const KNumber & left_op, const KNumber & right_op) +{ + return left_op << right_op; +} + +static KNumber ExecRsh(const KNumber & left_op, const KNumber & right_op) +{ + return left_op >> right_op; +} + +static KNumber ExecAdd(const KNumber & left_op, const KNumber & right_op) +{ + return left_op + right_op; +} + +static KNumber ExecSubtract(const KNumber & left_op, const KNumber & right_op) +{ + return left_op - right_op; +} + +static KNumber ExecMultiply(const KNumber & left_op, const KNumber & right_op) +{ + return left_op * right_op; +} + +static KNumber ExecDivide(const KNumber & left_op, const KNumber & right_op) +{ + return left_op / right_op; +} + +static KNumber ExecMod(const KNumber & left_op, const KNumber & right_op) +{ + return left_op % right_op; +} + +static KNumber ExecIntDiv(const KNumber & left_op, const KNumber & right_op) +{ + return (left_op / right_op).integerPart(); +} + +bool isoddint(const KNumber & input) +{ + if (input.type() != KNumber::IntegerType) return false; + // Routine to check if KNumber is an Odd integer + return ( (input / KNumber(2)).type() == KNumber::IntegerType); +} + +static KNumber ExecPower(const KNumber & left_op, const KNumber & right_op) +{ + return left_op.power(right_op); +} + +static KNumber ExecPwrRoot(const KNumber & left_op, const KNumber & right_op) +{ + return left_op.power(KNumber::One / right_op); +} + +static KNumber ExecAddP(const KNumber & left_op, const KNumber & right_op) +{ + return left_op * (KNumber::One + right_op/KNumber(100)); +} + +static KNumber ExecSubP(const KNumber & left_op, const KNumber & right_op) +{ + return left_op * (KNumber::One - right_op/KNumber(100)); +} + +static KNumber ExecMultiplyP(const KNumber & left_op, const KNumber & right_op) +{ + return left_op * right_op / KNumber(100); +} + +static KNumber ExecDivideP(const KNumber & left_op, const KNumber & right_op) +{ + return left_op * KNumber(100) / right_op; +} + + +// build precedence list +const struct operator_data CalcEngine::Operator[] = { + { 0, NULL, NULL}, // FUNC_EQUAL + { 0, NULL, NULL}, // FUNC_PERCENT + { 0, NULL, NULL}, // FUNC_BRACKET + { 1, ExecOr, NULL}, // FUNC_OR + { 2, ExecXor, NULL}, // FUNC_XOR + { 3, ExecAnd, NULL}, // FUNC_AND + { 4, ExecLsh, NULL}, // FUNC_LSH + { 4, ExecRsh, NULL}, // FUNC_RSH + { 5, ExecAdd, ExecAddP}, // FUNC_ADD + { 5, ExecSubtract, ExecSubP}, // FUNC_SUBTRACT + { 6, ExecMultiply, ExecMultiplyP}, // FUNC_MULTIPLY + { 6, ExecDivide, ExecDivideP}, // FUNC_DIVIDE + { 6, ExecMod, NULL}, // FUNC_MOD + { 6, ExecIntDiv, NULL}, // FUNC_INTDIV + { 7, ExecPower, NULL}, // FUNC_POWER + { 7, ExecPwrRoot, NULL} // FUNC_PWR_ROOT +}; + + +CalcEngine::CalcEngine() + : _percent_mode(false) +{ + // + // Basic initialization involves initializing the calcultion + // stack, and setting up the floating point excetion signal + // handler to trap the errors that the code can/has not been + // written to trap. + // + + struct sigaction fpe_trap; + + sigemptyset(&fpe_trap.sa_mask); + fpe_trap.sa_handler = &fpe_handler; +#ifdef SA_RESTART + fpe_trap.sa_flags = SA_RESTART; +#endif + sigaction(SIGFPE, &fpe_trap, NULL); + + _last_number = KNumber::Zero; + _error = false; +} + +KNumber CalcEngine::lastOutput(bool &error) const +{ + error = _error; + return _last_number; +} + +void CalcEngine::ArcCosDeg(KNumber input) +{ + if (input.type() == KNumber::SpecialType || + input < -KNumber::One || input > KNumber::One) { + _last_number = KNumber("nan"); + return; + } + + if (input.type() == KNumber::IntegerType) { + if (input == KNumber::One) { + _last_number = KNumber::Zero; + return; + } + if (input == - KNumber::One) { + _last_number = KNumber(180); + return; + } + if (input == KNumber::Zero) { + _last_number = KNumber(90); + return; + } + } + CALCAMNT tmp_num = static_cast<double>(input); + _last_number = Rad2Deg(KNumber(double(ACOS(tmp_num)))); +} + +void CalcEngine::ArcCosRad(KNumber input) +{ + if (input.type() == KNumber::SpecialType || + input < -KNumber::One || input > KNumber::One) { + _last_number = KNumber("nan"); + return; + } + CALCAMNT tmp_num = static_cast<double>(input); + _last_number = KNumber(double(ACOS(tmp_num))); +} + +void CalcEngine::ArcCosGrad(KNumber input) +{ + if (input.type() == KNumber::SpecialType || + input < -KNumber::One || input > KNumber::One) { + _last_number = KNumber("nan"); + return; + } + if (input.type() == KNumber::IntegerType) { + if (input == KNumber::One) { + _last_number = KNumber::Zero; + return; + } + if (input == - KNumber::One) { + _last_number = KNumber(200); + return; + } + if (input == KNumber::Zero) { + _last_number = KNumber(100); + return; + } + } + CALCAMNT tmp_num = static_cast<double>(input); + _last_number = Rad2Gra(KNumber(double(ACOS(tmp_num)))); +} + +void CalcEngine::ArcSinDeg(KNumber input) +{ + if (input.type() == KNumber::SpecialType || + input < -KNumber::One || input > KNumber::One) { + _last_number = KNumber("nan"); + return; + } + if (input.type() == KNumber::IntegerType) { + if (input == KNumber::One) { + _last_number = KNumber(90); + return; + } + if (input == - KNumber::One) { + _last_number = KNumber(-90); + return; + } + if (input == KNumber::Zero) { + _last_number = KNumber(0); + return; + } + } + CALCAMNT tmp_num = static_cast<double>(input); + _last_number = Rad2Deg(KNumber(double(ASIN(tmp_num)))); +} + +void CalcEngine::ArcSinRad(KNumber input) +{ + if (input.type() == KNumber::SpecialType || + input < -KNumber::One || input > KNumber::One) { + _last_number = KNumber("nan"); + return; + } + CALCAMNT tmp_num = static_cast<double>(input); + _last_number = KNumber(double(ASIN(tmp_num))); +} + +void CalcEngine::ArcSinGrad(KNumber input) +{ + if (input.type() == KNumber::SpecialType || + input < -KNumber::One || input > KNumber::One) { + _last_number = KNumber("nan"); + return; + } + if (input.type() == KNumber::IntegerType) { + if (input == KNumber::One) { + _last_number = KNumber(100); + return; + } + if (input == - KNumber::One) { + _last_number = KNumber(-100); + return; + } + if (input == KNumber::Zero) { + _last_number = KNumber(0); + return; + } + } + CALCAMNT tmp_num = static_cast<double>(input); + _last_number = Rad2Gra(KNumber(double(ASIN(tmp_num)))); +} + +void CalcEngine::ArcTangensDeg(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + if (input == KNumber("nan")) _last_number = KNumber("nan"); + if (input == KNumber("inf")) _last_number = KNumber(90); + if (input == KNumber("-inf")) _last_number = KNumber(-90); + return; + } + + CALCAMNT tmp_num = static_cast<double>(input); + _last_number = Rad2Deg(KNumber(double(ATAN(tmp_num)))); +} + +void CalcEngine::ArcTangensRad(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + if (input == KNumber("nan")) _last_number = KNumber("nan"); + if (input == KNumber("inf")) + _last_number = KNumber::Pi/KNumber(2); + if (input == KNumber("-inf")) + _last_number = -KNumber::Pi/KNumber(2); + return; + } + + CALCAMNT tmp_num = static_cast<double>(input); + _last_number = KNumber(double(ATAN(tmp_num))); +} + +void CalcEngine::ArcTangensGrad(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + if (input == KNumber("nan")) _last_number = KNumber("nan"); + if (input == KNumber("inf")) _last_number = KNumber(100); + if (input == KNumber("-inf")) _last_number = KNumber(-100); + return; + } + + CALCAMNT tmp_num = static_cast<double>(input); + _last_number = Rad2Gra(KNumber(double(ATAN(tmp_num)))); +} + +void CalcEngine::AreaCosHyp(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + if (input == KNumber("nan")) _last_number = KNumber("nan"); + if (input == KNumber("inf")) _last_number = KNumber("inf"); + if (input == KNumber("-inf")) _last_number = KNumber("nan"); + return; + } + + if (input < KNumber::One) { + _last_number = KNumber("nan"); + return; + } + if (input == KNumber::One) { + _last_number = KNumber::Zero; + return; + } + CALCAMNT tmp_num = static_cast<double>(input); + _last_number = KNumber(double(ACOSH(tmp_num))); +} + +void CalcEngine::AreaSinHyp(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + if (input == KNumber("nan")) _last_number = KNumber("nan"); + if (input == KNumber("inf")) _last_number = KNumber("inf"); + if (input == KNumber("-inf")) _last_number = KNumber("-inf"); + return; + } + + if (input == KNumber::Zero) { + _last_number = KNumber::Zero; + return; + } + CALCAMNT tmp_num = static_cast<double>(input); + _last_number = KNumber(double(ASINH(tmp_num))); +} + +void CalcEngine::AreaTangensHyp(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + _last_number = KNumber("nan"); + return; + } + + if (input < -KNumber::One || input > KNumber::One) { + _last_number = KNumber("nan"); + return; + } + if (input == KNumber::One) { + _last_number = KNumber("inf"); + return; + } + if (input == - KNumber::One) { + _last_number = KNumber("-inf"); + return; + } + CALCAMNT tmp_num = static_cast<double>(input); + _last_number = KNumber(double(ATANH(tmp_num))); +} + +void CalcEngine::Complement(KNumber input) +{ + if (input.type() != KNumber::IntegerType) + { + _last_number = KNumber("nan"); + return; + } + _last_number = - input - KNumber::One; +} + + + +// move a number into the interval [0,360) by adding multiples of 360 +static KNumber const moveIntoDegInterval(KNumber const &num) +{ + KNumber tmp_num = num - (num/KNumber(360)).integerPart() * KNumber(360); + if(tmp_num < KNumber::Zero) + return tmp_num + KNumber(360); + return tmp_num; +} + +// move a number into the interval [0,400) by adding multiples of 400 +static KNumber const moveIntoGradInterval(KNumber const &num) +{ + KNumber tmp_num = num - (num/KNumber(400)).integerPart() * KNumber(400); + if(tmp_num < KNumber::Zero) + return tmp_num + KNumber(400); + return tmp_num; +} + + +void CalcEngine::CosDeg(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + _last_number = KNumber("nan"); + return; + } + KNumber trunc_input = moveIntoDegInterval(input); + if (trunc_input.type() == KNumber::IntegerType) { + KNumber mult = trunc_input/KNumber(90); + if (mult.type() == KNumber::IntegerType) { + if (mult == KNumber::Zero) + _last_number = 1; + else if (mult == KNumber(1)) + _last_number = 0; + else if (mult == KNumber(2)) + _last_number = -1; + else if (mult == KNumber(3)) + _last_number = 0; + else qDebug("Something wrong in CalcEngine::CosDeg\n"); + return; + } + } + trunc_input = Deg2Rad(trunc_input); + + CALCAMNT tmp_num = static_cast<double>(trunc_input); + _last_number = KNumber(double(COS(tmp_num))); +} + +void CalcEngine::CosRad(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + _last_number = KNumber("nan"); + return; + } + CALCAMNT tmp_num = static_cast<double>(input); + _last_number = KNumber(double(COS(tmp_num))); +} + +void CalcEngine::CosGrad(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + _last_number = KNumber("nan"); + return; + } + KNumber trunc_input = moveIntoGradInterval(input); + if (trunc_input.type() == KNumber::IntegerType) { + KNumber mult = trunc_input/KNumber(100); + if (mult.type() == KNumber::IntegerType) { + if (mult == KNumber::Zero) + _last_number = 1; + else if (mult == KNumber(1)) + _last_number = 0; + else if (mult == KNumber(2)) + _last_number = -1; + else if (mult == KNumber(3)) + _last_number = 0; + else qDebug("Something wrong in CalcEngine::CosGrad\n"); + return; + } + } + trunc_input = Gra2Rad(trunc_input); + + CALCAMNT tmp_num = static_cast<double>(trunc_input); + _last_number = KNumber(double(COS(tmp_num))); +} + +void CalcEngine::CosHyp(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + if (input == KNumber("nan")) _last_number = KNumber("nan"); + if (input == KNumber("inf")) _last_number = KNumber("inf"); + if (input == KNumber("-inf")) _last_number = KNumber("inf"); + return; + } + + CALCAMNT tmp_num = static_cast<double>(input); + _last_number = KNumber(double(COSH(tmp_num))); +} + +void CalcEngine::Cube(KNumber input) +{ + _last_number = input*input*input; +} + +void CalcEngine::CubeRoot(KNumber input) +{ + _last_number = input.cbrt(); +} + +void CalcEngine::Exp(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + if (input == KNumber("nan")) _last_number = KNumber("nan"); + if (input == KNumber("inf")) _last_number = KNumber("inf"); + if (input == KNumber("-inf")) _last_number = KNumber::Zero; + return; + } + CALCAMNT tmp_num = static_cast<double>(input); + _last_number = KNumber(double(EXP(tmp_num))); +} + +void CalcEngine::Exp10(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + if (input == KNumber("nan")) _last_number = KNumber("nan"); + if (input == KNumber("inf")) _last_number = KNumber("inf"); + if (input == KNumber("-inf")) _last_number = KNumber::Zero; + return; + } + _last_number = KNumber(10).power(input); +} + + +static KNumber _factorial(KNumber input) +{ + KNumber tmp_amount = input; + + // don't do recursive factorial, + // because large numbers lead to + // stack overflows + while (tmp_amount > KNumber::One) + { + tmp_amount -= KNumber::One; + + input = tmp_amount * input; + + } + + if (tmp_amount < KNumber::One) + return KNumber::One; + return input; +} + + +void CalcEngine::Factorial(KNumber input) +{ + if (input == KNumber("inf")) return; + if (input < KNumber::Zero || input.type() == KNumber::SpecialType) + { + _error = true; + _last_number = KNumber("nan"); + return; + } + KNumber tmp_amount = input.integerPart(); + + _last_number = _factorial(tmp_amount); +} + +void CalcEngine::InvertSign(KNumber input) +{ + _last_number = -input; +} + +void CalcEngine::Ln(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + if (input == KNumber("nan")) _last_number = KNumber("nan"); + if (input == KNumber("inf")) _last_number = KNumber("inf"); + if (input == KNumber("-inf")) _last_number = KNumber("nan"); + return; + } + if (input < KNumber::Zero) + _last_number = KNumber("nan"); + else if (input == KNumber::Zero) + _last_number = KNumber("-inf"); + else if (input == KNumber::One) + _last_number = 0; + else { + CALCAMNT tmp_num = static_cast<double>(input); + _last_number = KNumber(double(LN(tmp_num))); + } +} + +void CalcEngine::Log10(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + if (input == KNumber("nan")) _last_number = KNumber("nan"); + if (input == KNumber("inf")) _last_number = KNumber("inf"); + if (input == KNumber("-inf")) _last_number = KNumber("nan"); + return; + } + if (input < KNumber::Zero) + _last_number = KNumber("nan"); + else if (input == KNumber::Zero) + _last_number = KNumber("-inf"); + else if (input == KNumber::One) + _last_number = 0; + else { + CALCAMNT tmp_num = static_cast<double>(input); + _last_number = KNumber(double(LOG_TEN(tmp_num))); + } +} + +void CalcEngine::ParenClose(KNumber input) +{ + // evaluate stack until corresponding opening bracket + while (!_stack.isEmpty()) + { + _node tmp_node = _stack.pop(); + if (tmp_node.operation == FUNC_BRACKET) + break; + input = evalOperation(tmp_node.number, tmp_node.operation, + input); + } + _last_number = input; + return; +} + +void CalcEngine::ParenOpen(KNumber input) +{ + enterOperation(input, FUNC_BRACKET); +} + +void CalcEngine::Reciprocal(KNumber input) +{ + _last_number = KNumber::One/input; +} + + +void CalcEngine::SinDeg(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + _last_number = KNumber("nan"); + return; + } + + KNumber trunc_input = moveIntoDegInterval(input); + if (trunc_input.type() == KNumber::IntegerType) { + KNumber mult = trunc_input/KNumber(90); + if (mult.type() == KNumber::IntegerType) { + if (mult == KNumber::Zero) + _last_number = 0; + else if (mult == KNumber(1)) + _last_number = 1; + else if (mult == KNumber(2)) + _last_number = 0; + else if (mult == KNumber(3)) + _last_number = -1; + else qDebug("Something wrong in CalcEngine::SinDeg\n"); + return; + } + } + trunc_input = Deg2Rad(trunc_input); + + CALCAMNT tmp_num = static_cast<double>(trunc_input); + _last_number = KNumber(double(SIN(tmp_num))); +} + +void CalcEngine::SinRad(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + _last_number = KNumber("nan"); + return; + } + + CALCAMNT tmp_num = static_cast<double>(input); + _last_number = KNumber(double(SIN(tmp_num))); +} + +void CalcEngine::SinGrad(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + _last_number = KNumber("nan"); + return; + } + + KNumber trunc_input = moveIntoGradInterval(input); + if (trunc_input.type() == KNumber::IntegerType) { + KNumber mult = trunc_input/KNumber(100); + if (mult.type() == KNumber::IntegerType) { + if (mult == KNumber::Zero) + _last_number = 0; + else if (mult == KNumber(1)) + _last_number = 1; + else if (mult == KNumber(2)) + _last_number = 0; + else if (mult == KNumber(3)) + _last_number = -1; + else qDebug("Something wrong in CalcEngine::SinGrad\n"); + return; + } + } + + trunc_input = Gra2Rad(trunc_input); + + CALCAMNT tmp_num = static_cast<double>(trunc_input); + _last_number = KNumber(double(SIN(tmp_num))); +} + +void CalcEngine::SinHyp(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + if (input == KNumber("nan")) _last_number = KNumber("nan"); + if (input == KNumber("inf")) _last_number = KNumber("inf"); + if (input == KNumber("-inf")) _last_number = KNumber("-inf"); + return; + } + + CALCAMNT tmp_num = static_cast<double>(input); + _last_number = KNumber(double(SINH(tmp_num))); +} + +void CalcEngine::Square(KNumber input) +{ + _last_number = input*input; +} + +void CalcEngine::SquareRoot(KNumber input) +{ + _last_number = input.sqrt(); +} + +void CalcEngine::StatClearAll(KNumber input) +{ + UNUSED(input); + stats.clearAll(); +} + +void CalcEngine::StatCount(KNumber input) +{ + UNUSED(input); + _last_number = KNumber(stats.count()); +} + +void CalcEngine::StatDataNew(KNumber input) +{ + stats.enterData(input); + _last_number = KNumber(stats.count()); +} + +void CalcEngine::StatDataDel(KNumber input) +{ + UNUSED(input); + stats.clearLast(); + _last_number = KNumber::Zero; +} + +void CalcEngine::StatMean(KNumber input) +{ + UNUSED(input); + _last_number = stats.mean(); + + _error = stats.error(); +} + +void CalcEngine::StatMedian(KNumber input) +{ + UNUSED(input); + _last_number = stats.median(); + + _error = stats.error(); +} + +void CalcEngine::StatStdDeviation(KNumber input) +{ + UNUSED(input); + _last_number = stats.std(); + + _error = stats.error(); +} + +void CalcEngine::StatStdSample(KNumber input) +{ + UNUSED(input); + _last_number = stats.sample_std(); + + _error = stats.error(); +} + +void CalcEngine::StatSum(KNumber input) +{ + UNUSED(input); + _last_number = stats.sum(); +} + +void CalcEngine::StatSumSquares(KNumber input) +{ + UNUSED(input); + _last_number = stats.sum_of_squares(); + + _error = stats.error(); +} + +void CalcEngine::TangensDeg(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + _last_number = KNumber("nan"); + return; + } + + SinDeg(input); + KNumber arg1 = _last_number; + CosDeg(input); + KNumber arg2 = _last_number; + _last_number = arg1 / arg2; +} + +void CalcEngine::TangensRad(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + _last_number = KNumber("nan"); + return; + } + + SinRad(input); + KNumber arg1 = _last_number; + CosRad(input); + KNumber arg2 = _last_number; + _last_number = arg1 / arg2; +} + +void CalcEngine::TangensGrad(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + _last_number = KNumber("nan"); + return; + } + + SinGrad(input); + KNumber arg1 = _last_number; + CosGrad(input); + KNumber arg2 = _last_number; + _last_number = arg1 / arg2; +} + +void CalcEngine::TangensHyp(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + if (input == KNumber("nan")) _last_number = KNumber("nan"); + if (input == KNumber("inf")) _last_number = KNumber::One; + if (input == KNumber("-inf")) _last_number = KNumber::MinusOne; + return; + } + + CALCAMNT tmp_num = static_cast<double>(input); + _last_number = KNumber(double(TANH(tmp_num))); +} + +KNumber CalcEngine::evalOperation(KNumber arg1, Operation operation, + KNumber arg2) +{ + if (!_percent_mode || Operator[operation].prcnt_ptr == NULL) + { + return (Operator[operation].arith_ptr)(arg1, arg2); + } else { + _percent_mode = false; + return (Operator[operation].prcnt_ptr)(arg1, arg2); + } +} + +void CalcEngine::enterOperation(KNumber number, Operation func) +{ + _node tmp_node; + + if (func == FUNC_BRACKET) + { + tmp_node.number = 0; + tmp_node.operation = FUNC_BRACKET; + + _stack.push(tmp_node); + + return; + } + + if (func == FUNC_PERCENT) + { + _percent_mode = true; + } + + tmp_node.number = number; + tmp_node.operation = func; + + _stack.push(tmp_node); + + evalStack(); +} + +bool CalcEngine::evalStack(void) +{ + // this should never happen + if (_stack.isEmpty()) KMessageBox::error(0L, i18n("Stack processing error - empty stack")); + + _node tmp_node = _stack.pop(); + + while (! _stack.isEmpty()) + { + _node tmp_node2 = _stack.pop(); + if (Operator[tmp_node.operation].precedence <= + Operator[tmp_node2.operation].precedence) + { + if (tmp_node2.operation == FUNC_BRACKET) continue; + KNumber tmp_result = + evalOperation(tmp_node2.number, tmp_node2.operation, + tmp_node.number); + tmp_node.number = tmp_result; + } + else + { + _stack.push(tmp_node2); + break; + } + + } + + if(tmp_node.operation != FUNC_EQUAL && tmp_node.operation != FUNC_PERCENT) + _stack.push(tmp_node); + + _last_number = tmp_node.number; + return true; +} + +void CalcEngine::Reset() +{ + _error = false; + _last_number = KNumber::Zero; + + _stack.clear(); +} + + diff --git a/kcalc/kcalc_core.h b/kcalc/kcalc_core.h new file mode 100644 index 0000000..edd33f3 --- /dev/null +++ b/kcalc/kcalc_core.h @@ -0,0 +1,181 @@ +/* + + KCalc, a scientific calculator for the X window system using the + Qt widget libraries, available at no cost at http://www.troll.no + + Copyright (C) 1996 Bernd Johannes Wuebben + wuebben@math.cornell.edu + + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef _KCALC_CORE_H +#define _KCALC_CORE_H + +#include "stats.h" +#include <qvaluestack.h> +#include "knumber.h" + +#define POS_ZERO 1e-19L /* What we consider zero is */ +#define NEG_ZERO -1e-19L /* anything between these two */ + + +typedef KNumber (*Arith)(const KNumber &, const KNumber &); +typedef KNumber (*Prcnt)(const KNumber &, const KNumber &); + +#define UNUSED(x) ((void)(x)) + + + +struct operator_data { + int precedence; // priority of operators in " enum Operation" + Arith arith_ptr; + Prcnt prcnt_ptr; +}; + +class CalcEngine +{ + public: + // operations that can be stored in calculation stack + enum Operation { + FUNC_EQUAL, + FUNC_PERCENT, + FUNC_BRACKET, + FUNC_OR, + FUNC_XOR, + FUNC_AND, + FUNC_LSH, + FUNC_RSH, + FUNC_ADD, + FUNC_SUBTRACT, + FUNC_MULTIPLY, + FUNC_DIVIDE, + FUNC_MOD, + FUNC_INTDIV, + FUNC_POWER, + FUNC_PWR_ROOT + }; + + CalcEngine(); + + KNumber lastOutput(bool &error) const; + + void enterOperation(KNumber num, Operation func); + + + void ArcCosDeg(KNumber input); + void ArcCosRad(KNumber input); + void ArcCosGrad(KNumber input); + void ArcSinDeg(KNumber input); + void ArcSinRad(KNumber input); + void ArcSinGrad(KNumber input); + void ArcTangensDeg(KNumber input); + void ArcTangensRad(KNumber input); + void ArcTangensGrad(KNumber input); + void AreaCosHyp(KNumber input); + void AreaSinHyp(KNumber input); + void AreaTangensHyp(KNumber input); + void Complement(KNumber input); + void CosDeg(KNumber input); + void CosRad(KNumber input); + void CosGrad(KNumber input); + void CosHyp(KNumber input); + void Cube(KNumber input); + void CubeRoot(KNumber input); + void Exp(KNumber input); + void Exp10(KNumber input); + void Factorial(KNumber input); + void InvertSign(KNumber input); + void Ln(KNumber input); + void Log10(KNumber input); + void ParenClose(KNumber input); + void ParenOpen(KNumber input); + void Reciprocal(KNumber input); + void SinDeg(KNumber input); + void SinGrad(KNumber input); + void SinRad(KNumber input); + void SinHyp(KNumber input); + void Square(KNumber input); + void SquareRoot(KNumber input); + void StatClearAll(KNumber input); + void StatCount(KNumber input); + void StatDataNew(KNumber input); + void StatDataDel(KNumber input); + void StatMean(KNumber input); + void StatMedian(KNumber input); + void StatStdDeviation(KNumber input); + void StatStdSample(KNumber input); + void StatSum(KNumber input); + void StatSumSquares(KNumber input); + void TangensDeg(KNumber input); + void TangensRad(KNumber input); + void TangensGrad(KNumber input); + void TangensHyp(KNumber input); + + void Reset(); + private: + KStats stats; + + typedef struct { + KNumber number; + Operation operation; + } _node; + + // Stack holds all operations and numbers that have not yet been + // processed, e.g. user types "2+3*", the calculation can not be + // executed, because "*" has a higher precedence than "+", so we + // need to wait for the next number. + // + // In the stack this would be stored as ((2,+),(3,*),...) + // + // "enterOperation": If the introduced Operation has lower priority + // than the preceding operations in the stack, then we can start to + // evaluate the stack (with "evalStack"). Otherwise we append the new + // Operation and number to the stack. + // + // E.g. "2*3+" evaluates to "6+", but "2+3*" can not be evaluated + // yet. + // + // We also take care of brackets, by writing a marker "FUNC_BRACKET" + // into the stack, each time the user opens one. When a bracket is + // closed, everything in the stack is evaluated until the first + // marker "FUNC_BRACKET" found. + QValueStack<_node> _stack; + + KNumber _last_number; + + bool _percent_mode; + + + static const struct operator_data Operator[]; + + bool evalStack(void); + + KNumber evalOperation(KNumber arg1, Operation operation, KNumber arg2); + + const KNumber Deg2Rad(const KNumber &x) const + { return KNumber(2) * KNumber::Pi / KNumber(360) * x; } + const KNumber Gra2Rad(const KNumber &x) const + { return KNumber(2)*KNumber::Pi / KNumber(400) * x; } + const KNumber Rad2Deg(const KNumber &x) const + { return KNumber(360) / (KNumber(2) * KNumber::Pi) * x; } + const KNumber Rad2Gra(const KNumber &x) const + { return KNumber(400) / (KNumber(2)*KNumber::Pi) * x; } + +}; + + +#endif //_KCALC_CORE_H diff --git a/kcalc/kcalc_settings.kcfgc b/kcalc/kcalc_settings.kcfgc new file mode 100644 index 0000000..ac8bd41 --- /dev/null +++ b/kcalc/kcalc_settings.kcfgc @@ -0,0 +1,8 @@ +# Code generation options for kconfig_compiler +File=kcalc.kcfg +ClassName=KCalcSettings +Singleton=true +Mutators=ShowStat,ShowScientific,ShowLogic,ShowConstants,nameConstant,valueConstant +# Inherits=KConfigSkeleton +# IncludeFiles=libkdepim/kpimprefs.h +# MemberVariables=public diff --git a/kcalc/kcalcdisplay.cpp b/kcalc/kcalcdisplay.cpp new file mode 100644 index 0000000..672c363 --- /dev/null +++ b/kcalc/kcalcdisplay.cpp @@ -0,0 +1,608 @@ +/* + $Id$ + + KCalc, a scientific calculator for the X window system using the + Qt widget libraries, available at no cost at http://www.troll.no + + Copyright (C) 1996 Bernd Johannes Wuebben + wuebben@math.cornell.edu + + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include <errno.h> +#include <stdlib.h> +#include <ctype.h> + +#include <qclipboard.h> +#include <qpainter.h> +#include <qregexp.h> + +#include <kglobal.h> +#include <klocale.h> +#include <knotifyclient.h> +#include "kcalc_settings.h" +#include "kcalcdisplay.h" +#include "kcalcdisplay.moc" + + +KCalcDisplay::KCalcDisplay(QWidget *parent, const char *name) + :QLabel(parent,name), _beep(false), _groupdigits(false), _button(0), _lit(false), + _num_base(NB_DECIMAL), _precision(9), + _fixed_precision(-1), _display_amount(0), + selection_timer(new QTimer) +{ + setFrameStyle(QFrame::WinPanel | QFrame::Sunken); + setAlignment(AlignRight | AlignVCenter); + setFocus(); + setFocusPolicy(QWidget::StrongFocus); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed, false); + + connect(this, SIGNAL(clicked()), this, SLOT(slotDisplaySelected())); + + connect(selection_timer, SIGNAL(timeout()), + this, SLOT(slotSelectionTimedOut())); + + sendEvent(EventReset); +} + +KCalcDisplay::~KCalcDisplay() +{ + delete selection_timer; +} + +bool KCalcDisplay::sendEvent(Event const event) +{ + switch(event) + { + case EventReset: + _display_amount = 0; + _str_int = "0"; + _str_int_exp = QString::null; + + _eestate = false; + _period = false; + _neg_sign = false; + + updateDisplay(); + + return true; + case EventClear: + return sendEvent(EventReset); + case EventChangeSign: + return changeSign(); + case EventError: + updateDisplay(); + + return true; + default: + return false; + } +} + + +void KCalcDisplay::slotCut(void) +{ + slotCopy(); + sendEvent(EventReset); +} + +void KCalcDisplay::slotCopy(void) +{ + QString txt = QLabel::text(); + if (_num_base == NB_HEX) + txt.prepend( "0x" ); + (QApplication::clipboard())->setText(txt, QClipboard::Clipboard); + (QApplication::clipboard())->setText(txt, QClipboard::Selection); +} + +void KCalcDisplay::slotPaste(bool bClipboard) +{ + QString tmp_str = (QApplication::clipboard())->text(bClipboard ? QClipboard::Clipboard : QClipboard::Selection); + + if (tmp_str.isNull()) + { + if (_beep) KNotifyClient::beep(); + return; + } + + NumBase tmp_num_base = _num_base; + + tmp_str = tmp_str.stripWhiteSpace(); + + if (tmp_str.startsWith("0x", false)) + tmp_num_base = NB_HEX; + + if (tmp_num_base != NB_DECIMAL) + { + bool was_ok; + unsigned long long int tmp_result = tmp_str.toULongLong(& was_ok, tmp_num_base); + + if (!was_ok) + { + setAmount(KNumber::NotDefined); + if(_beep) KNotifyClient::beep(); + return ; + } + + setAmount(KNumber(tmp_result)); + } + else // _num_base == NB_DECIMAL && ! tmp_str.startsWith("0x", false) + { + setAmount(KNumber(tmp_str)); + if (_beep && _display_amount == KNumber::NotDefined) + KNotifyClient::beep(); + } +} + +void KCalcDisplay::slotDisplaySelected(void) +{ + if(_button == LeftButton) { + if(_lit) { + slotCopy(); + selection_timer->start(100); + } else { + selection_timer->stop(); + } + + invertColors(); + } else { + slotPaste(false); // Selection + } +} + +void KCalcDisplay::slotSelectionTimedOut(void) +{ + _lit = false; + invertColors(); + selection_timer->stop(); +} + +void KCalcDisplay::invertColors() +{ + QColor tmp_col(paletteBackgroundColor()); + setPaletteBackgroundColor(paletteForegroundColor()); + setPaletteForegroundColor(tmp_col); +} + + + +void KCalcDisplay::mousePressEvent(QMouseEvent *e) +{ + if(e->button() == LeftButton) { + _lit = !_lit; + _button = LeftButton; + } else { + _button = MidButton; + } + + emit clicked(); +} + +void KCalcDisplay::setPrecision(int precision) +{ + _precision = precision; +} + +void KCalcDisplay::setFixedPrecision(int precision) +{ + if (_fixed_precision > _precision) + _fixed_precision = -1; + else + _fixed_precision = precision; +} + +void KCalcDisplay::setBeep(bool flag) +{ + _beep = flag; +} + +void KCalcDisplay::setGroupDigits(bool flag) +{ + _groupdigits = flag; +} + +KNumber const & KCalcDisplay::getAmount(void) const +{ + return _display_amount; +} + + +bool KCalcDisplay::setAmount(KNumber const & new_amount) +{ + QString display_str; + + _str_int = "0"; + _str_int_exp = QString::null; + _period = false; + _neg_sign = false; + _eestate = false; + + if (_num_base != NB_DECIMAL && new_amount.type() != KNumber::SpecialType) + { + _display_amount = new_amount.integerPart(); + unsigned long long int tmp_workaround = static_cast<unsigned long long int>(_display_amount); + + display_str = QString::number(tmp_workaround, _num_base).upper(); + } + else // _num_base == NB_DECIMAL || new_amount.type() == + // KNumber::SpecialType + { + _display_amount = new_amount; + + display_str = _display_amount.toQString(KCalcSettings::precision(), _fixed_precision); +#if 0 + else if (_display_amount > 1.0e+16) + display_str = QCString().sprintf(PRINT_LONG_BIG, _precision + 1, _display_amount); + else + display_str = QCString().sprintf(PRINT_LONG_BIG, _precision, _display_amount); +#endif + } + + setText(display_str); + return true; + +} + +void KCalcDisplay::setText(QString const &string) +{ + QString localizedString = string; + + // If we aren't in decimal mode, we don't need to modify the string + if (_num_base == NB_DECIMAL && _groupdigits) + // when input ends with "." (because uncomplete), the + // formatNumber-method does not work; fix by hand by + // truncating, formatting and appending again + if (string.endsWith(".")) { + localizedString.truncate(localizedString.length() - 1); + localizedString = KGlobal::locale()->formatNumber(localizedString, false, 0); // Note: rounding happened already above! + localizedString.append(KGlobal::locale()->decimalSymbol()); + } else + localizedString = KGlobal::locale()->formatNumber(string, false, 0); // Note: rounding happened already above! + + QLabel::setText(localizedString); + emit changedText(localizedString); +} + +QString KCalcDisplay::text() const +{ + if (_num_base != NB_DECIMAL) + return QLabel::text(); + QString display_str = _display_amount.toQString(KCalcSettings::precision()); + + return display_str; + // return QCString().sprintf(PRINT_LONG_BIG, 40, _display_amount); +} + +/* change representation of display to new base (i.e. binary, decimal, + octal, hexadecimal). The amount being displayed is changed to this + base, but for now this amount can not be modified anymore (like + being set with "setAmount"). Return value is the new base. */ +int KCalcDisplay::setBase(NumBase new_base) +{ + CALCAMNT tmp_val = static_cast<unsigned long long int>(getAmount()); + + switch(new_base) + { + case NB_HEX: + _num_base = NB_HEX; + _period = false; + break; + case NB_DECIMAL: + _num_base = NB_DECIMAL; + break; + case NB_OCTAL: + _num_base = NB_OCTAL; + _period = false; + break; + case NB_BINARY: + _num_base = NB_BINARY; + _period = false; + break; + default: // we shouldn't ever end up here + _num_base = NB_DECIMAL; + } + + setAmount(static_cast<unsigned long long int>(tmp_val)); + + return _num_base; +} + +void KCalcDisplay::setStatusText(uint i, const QString& text) +{ + if (i < NUM_STATUS_TEXT) + _str_status[i] = text; + update(); +} + +bool KCalcDisplay::updateDisplay(void) +{ + // Put sign in front. + QString tmp_string; + if(_neg_sign == true) + tmp_string = "-" + _str_int; + else + tmp_string = _str_int; + + switch(_num_base) + { + case NB_BINARY: + Q_ASSERT(_period == false && _eestate == false); + setText(tmp_string); + _display_amount = static_cast<unsigned long long int>(STRTOUL(_str_int.latin1(), 0, 2)); + if (_neg_sign) + _display_amount = -_display_amount; + //str_size = cvb(_str_int, boh_work, DSP_SIZE); + break; + + case NB_OCTAL: + Q_ASSERT(_period == false && _eestate == false); + setText(tmp_string); + _display_amount = static_cast<unsigned long long int>(STRTOUL(_str_int.latin1(), 0, 8)); + if (_neg_sign) + _display_amount = -_display_amount; + break; + + case NB_HEX: + Q_ASSERT(_period == false && _eestate == false); + setText(tmp_string); + _display_amount = static_cast<unsigned long long int>(STRTOUL(_str_int.latin1(), 0, 16)); + if (_neg_sign) + _display_amount = -_display_amount; + break; + + case NB_DECIMAL: + if(_eestate == false) + { + setText(tmp_string); + _display_amount = tmp_string; + } + else + { + if(_str_int_exp.isNull()) + { + // add 'e0' to display but not to conversion + _display_amount = tmp_string; + setText(tmp_string + "e0"); + } + else + { + tmp_string += 'e' + _str_int_exp; + setText(tmp_string); + _display_amount = tmp_string; + } + } + break; + + default: + return false; + } + + return true; +} + +void KCalcDisplay::newCharacter(char const new_char) +{ + // test if character is valid + switch(new_char) + { + case 'e': + // EE can be set only once and in decimal mode + if (_num_base != NB_DECIMAL || + _eestate == true) + { + if(_beep) KNotifyClient::beep(); + return; + } + _eestate = true; + break; + + case '.': + // Period can be set only once and only in decimal + // mode, also not in EE-mode + if (_num_base != NB_DECIMAL || + _period == true || + _eestate == true) + { + if(_beep) KNotifyClient::beep(); + return; + } + _period = true; + break; + + case 'F': + case 'E': + case 'D': + case 'C': + case 'B': + case 'A': + if (_num_base == NB_DECIMAL) + { + if(_beep) KNotifyClient::beep(); + return; + } + // no break + case '9': + case '8': + if (_num_base == NB_OCTAL) + { + if(_beep) KNotifyClient::beep(); + return; + } + // no break + case '7': + case '6': + case '5': + case '4': + case '3': + case '2': + if (_num_base == NB_BINARY) + { + if(_beep) KNotifyClient::beep(); + return; + } + // no break + case '1': + case '0': + break; + + default: + if(_beep) KNotifyClient::beep(); + return; + } + + // change exponent or mantissa + if (_eestate) + { + // ignore ',' before 'e'. turn e.g. '123.e' into '123e' + if (new_char == 'e' && _str_int.endsWith( "." )) + { + _str_int.truncate(_str_int.length() - 1); + _period = false; + } + + // 'e' only starts ee_mode, leaves strings unchanged + if (new_char != 'e' && + // do not add '0' if at start of exp + !(_str_int_exp.isNull() && new_char == '0')) + _str_int_exp.append(new_char); + } + else + { + // handle first character + if (_str_int == "0") + { + switch(new_char) + { + case '.': + // display "0." not just "." + _str_int.append(new_char); + break; + case 'e': + // display "0e" not just "e" + // "0e" does not make sense either, but... + _str_int.append(new_char); + break; + default: + // no leading '0's + _str_int[0] = new_char; + } + } + else + _str_int.append(new_char); + } + + updateDisplay(); +} + +void KCalcDisplay::deleteLastDigit(void) +{ + // Only partially implemented !! + if (_eestate) + { + if(_str_int_exp.isNull()) + { + _eestate = false; + } + else + { + int length = _str_int_exp.length(); + if(length > 1) + { + _str_int_exp.truncate(length-1); + } + else + { + _str_int_exp = (char *)0; + } + } + } + else + { + int length = _str_int.length(); + if(length > 1) + { + if (_str_int[length-1] == '.') + _period = false; + _str_int.truncate(length-1); + } + else + { + Q_ASSERT(_period == false); + _str_int[0] = '0'; + } + } + + updateDisplay(); +} + +// change Sign of display. Problem: Only possible here, when in input +// mode. Otherwise return 'false' so that the kcalc_core can handle +// things. +bool KCalcDisplay::changeSign(void) +{ + //stupid way, to see if in input_mode or display_mode + if (_str_int == "0") return false; + + if(_eestate) + { + if(!_str_int_exp.isNull()) + { + if (_str_int_exp[0] != '-') + _str_int_exp.prepend('-'); + else + _str_int_exp.remove('-'); + } + } + else + { + _neg_sign = ! _neg_sign; + } + + updateDisplay(); + + return true; +} + +void KCalcDisplay::drawContents(QPainter *p) +{ + QLabel::drawContents(p); + + // draw the status texts using half of the normal + // font size but not smaller than 7pt + QFont f(font()); + f.setPointSize(QMAX((f.pointSize() / 2), 7)); + p->setFont(f); + QFontMetrics fm(f); + uint w = fm.width("_____"); + uint h = fm.height(); + + for (uint i = 0; i < NUM_STATUS_TEXT; i++) + { + p->drawText(5 + i * w, h, _str_status[i]); + } +} + +// Return the QLabel's normal size hint vertically expanded +// by half the font height to make room for the status texts +QSize KCalcDisplay::sizeHint() const +{ + QFont f(font()); + f.setPointSize(QMAX((f.pointSize() / 2), 7)); + QFontMetrics fm(f); + return QLabel::sizeHint() + QSize(0, fm.height()); +} + diff --git a/kcalc/kcalcdisplay.h b/kcalc/kcalcdisplay.h new file mode 100644 index 0000000..4f72fb7 --- /dev/null +++ b/kcalc/kcalcdisplay.h @@ -0,0 +1,152 @@ +/* + + KCalc + + Copyright (C) Bernd Johannes Wuebben + wuebben@math.cornell.edu + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + */ + + +#ifndef _D_KCALCDISPLAY_H_ +#define _D_KCALCDISPLAY_H_ + +#include <stdlib.h> +#include <qlabel.h> +#include <qtimer.h> +#include "knumber.h" +#include "kcalctype.h" + +#if defined HAVE_LONG_DOUBLE && defined HAVE_L_FUNCS + #define PRINT_FLOAT "%.*Lf" + #define PRINT_LONG_BIG "%.*Lg" + #define PRINT_LONG "%Lg" +#else + #define PRINT_FLOAT "%.*f" + #define PRINT_LONG_BIG "%.*g" + #define PRINT_LONG "%g" +#endif + +#ifdef HAVE_LONG_LONG + #define PRINT_OCTAL "%llo" + #define PRINT_HEX "%llX" +#else + #define PRINT_OCTAL "%lo" + #define PRINT_HEX "%lX" +#endif + +#define NUM_STATUS_TEXT 4 + +/* + This class provides a pocket calculator display. The display has + implicitely two major modes: One is for editing and one is purely + for displaying. + + When one uses "setAmount", the given amount is displayed, and the + amount which was possibly typed in before is lost. At the same time + this new value can not be modified. + + On the other hand, "addNewChar" adds a new digit to the amount that + is being typed in. If "setAmount" was used before, the display is + cleared and a new input starts. + + TODO: Check overflows, number of digits and such... +*/ + +enum NumBase { + NB_BINARY = 2, + NB_OCTAL = 8, + NB_DECIMAL = 10, + NB_HEX = 16 +}; + + +class KCalcDisplay : public QLabel +{ +Q_OBJECT + +public: + KCalcDisplay(QWidget *parent=0, const char *name=0); + ~KCalcDisplay(); + +protected: + void mousePressEvent ( QMouseEvent *); + virtual void drawContents(QPainter *p); + +public: + enum Event { + EventReset, // resets display + EventClear, // if no _error reset display + EventError, + EventChangeSign + }; + bool sendEvent(Event const event); + void deleteLastDigit(void); + KNumber const & getAmount(void) const; + void newCharacter(char const new_char); + bool setAmount(KNumber const & new_amount); + int setBase(NumBase new_base); + void setBeep(bool flag); + void setGroupDigits(bool flag); + void setFixedPrecision(int precision); + void setPrecision(int precision); + void setText(QString const &string); + QString text() const; + bool updateDisplay(void); + void setStatusText(uint i, const QString& text); + virtual QSize sizeHint() const; +private: + bool _beep; + bool _groupdigits; + int _button; + bool _lit; + NumBase _num_base; + + int _precision; + int _fixed_precision; // "-1" = no fixed_precision + + KNumber _display_amount; +private: + bool changeSign(void); + void invertColors(void); + + // only used for input of new numbers + bool _eestate; + bool _period; + bool _neg_sign; + QString _str_int; + QString _str_int_exp; + QString _str_status[NUM_STATUS_TEXT]; + + QTimer* selection_timer; + +signals: + void clicked(void); + void changedText(QString const &); + +public slots: + void slotCut(void); + void slotCopy(void); + void slotPaste(bool bClipboard=true); + +private slots: + void slotSelectionTimedOut(void); + void slotDisplaySelected(void); +}; + +#endif // _KCALCDISPLAY_H_ diff --git a/kcalc/kcalcrc.upd b/kcalc/kcalcrc.upd new file mode 100644 index 0000000..463da95 --- /dev/null +++ b/kcalc/kcalcrc.upd @@ -0,0 +1,4 @@ +Id=KDE_3_2_0 +File=kcalcrc +Group=General +Key=style,Statistical diff --git a/kcalc/kcalctype.h b/kcalc/kcalctype.h new file mode 100644 index 0000000..8223e87 --- /dev/null +++ b/kcalc/kcalctype.h @@ -0,0 +1,135 @@ +/* + $Id$ + + KCalc, a scientific calculator for the X window system using the + Qt widget libraries, available at no cost at http://www.troll.no + + Copyright (C) 1996 Bernd Johannes Wuebben + wuebben@math.cornell.edu + + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifdef HAVE_CONFIG_H + #include "../config.h" +#endif + +#ifndef KCALC_TYPE_H +#define KCALC_TYPE_H + +#include <limits.h> +#include <float.h> +#include <math.h> + +#if defined(HAVE_LONG_DOUBLE) && defined(HAVE_L_FUNCS) +/* should be detected by autoconf and defined in config.h + Be carefull when modifying these lines. HAVE_LONG_DOUBLE + is used all over kcalc's sources to determine whether + long double of double is the fundamental data type for kcalc*/ + + + + typedef long double CALCAMNT; +#else + typedef double CALCAMNT; +#endif + + + +#if defined(HAVE_LONG_DOUBLE) && defined(HAVE_L_FUNCS) + #define MODF(X,Y) modfl(X,Y) + #define SIN(X) sinl(X) + #define ASIN(X) asinl(X) + #define SINH(X) sinhl(X) + #define ASINH(X) asinhl(X) + #define COS(X) cosl(X) + #define COSH(X) coshl(X) + #define ACOS(X) acosl(X) + #define ACOSH(X) acoshl(X) + #define TAN(X) tanl(X) + #define TANH(X) tanhl(X) + #define ATAN(X) atanl(X) + #define ATANH(X) atanhl(X) + #define EXP(X) expl(X) + #define POW(X,Y) powl(X,Y) + #define LN(X) logl(X) + #define LOG_TEN(X) log10l(X) + #define SQRT(X) sqrtl(X) + #define CBRT(X) cbrtl(X) + #define ISINF(X) isinfl(X) + #define STRTOD(X,Y) strtold(X,Y) + #define ROUND(X) roundl(X) + #define CALCAMNT_EPSILON LDBL_EPSILON +#else + #define MODF(X,Y) modf(X,Y) + #define SIN(X) sin(X) + #define ASIN(X) asin(X) + #define SINH(X) sinh(X) + #define ASINH(X) asinh(X) + #define COS(X) cos(X) + #define COSH(X) cosh(X) + #define ACOS(X) acos(X) + #define ACOSH(X) acosh(X) + #define TAN(X) tan(X) + #define TANH(X) tanh(X) + #define ATAN(X) atan(X) + #define ATANH(X) atanh(X) + #define EXP(X) exp(X) + #define POW(X,Y) pow(X,Y) + #define LN(X) log(X) + #define LOG_TEN(X) log10(X) + #define SQRT(X) sqrt(X) + #define CBRT(X) cbrt(X) + #define ISINF(X) isinf(X) + #define STRTOD(X,Y) strtod(X,Y) + #define ROUND(X) round(X) + #define CALCAMNT_EPSILON DBL_EPSILON +#endif + +#if !defined(HAVE_FUNC_ROUND) && !defined(HAVE_FUNC_ROUNDL) + #undef ROUND + #define ROUND(X) rint(X) +#endif + +#undef HAVE_LONG_LONG +#if defined(LLONG_MAX) && defined(HAVE_LONG_DOUBLE) +#define KCALC_LONG_MIN LLONG_MIN +#define KCALC_LONG_MAX LLONG_MAX +#define KCALC_ULONG_MAX ULLONG_MAX +#define KCALC_LONG long long +#define HAVE_LONG_LONG +#define STRTOUL strtoull +#else +#if defined(LONG_LONG_MAX) && defined(HAVE_LONG_DOUBLE) +#define KCALC_LONG_MIN LONG_LONG_MIN +#define KCALC_LONG_MAX LONG_LONG_MAX +#define KCALC_ULONG_MAX ULONG_LONG_MAX +#define KCALC_LONG long long +#define HAVE_LONG_LONG +#ifdef _HPUX_SOURCE +#define STRTOUL strtoul +#else +#define STRTOUL strtoull +#endif +#else +#define KCALC_LONG_MIN LONG_MIN +#define KCALC_LONG_MAX LONG_MAX +#define KCALC_ULONG_MAX ULONG_MAX +#define KCALC_LONG long +#define STRTOUL strtoul +#endif +#endif +#endif diff --git a/kcalc/kcalcui.rc b/kcalc/kcalcui.rc new file mode 100644 index 0000000..e79c350 --- /dev/null +++ b/kcalc/kcalcui.rc @@ -0,0 +1,17 @@ +<!DOCTYPE kpartgui> +<kpartgui name="kcalc" version="19"> +<MenuBar> + <Menu name="settings" noMerge="1"><text>&Settings</text> + <Action name="show_science"/> + <Action name="show_stat"/> + <Action name="show_logic"/> + <Action name="show_constants"/> + <Separator/> + <Action name="show_all"/> + <Action name="hide_all"/> + <Separator/> + <Action name="options_configure_keybinding"/> + <Action name="options_configure"/> + </Menu> +</MenuBar> +</kpartgui> diff --git a/kcalc/knumber/Makefile.am b/kcalc/knumber/Makefile.am new file mode 100644 index 0000000..6e5673b --- /dev/null +++ b/kcalc/knumber/Makefile.am @@ -0,0 +1,16 @@ +AM_CPPFLAGS=-D_GNU_SOURCE -D_ISOC99_SOURCE $(all_includes) + +SUBDIRS = tests + +bin_PROGRAMS = +lib_LTLIBRARIES = +noinst_LTLIBRARIES = libknumber.la + +libknumber_la_SOURCES = knumber.cpp knumber_priv.cpp +libknumber_la_LIBADD = $(LIBGMP) -lm + +METASOURCES = AUTO + +noinst_HEADERS = knumber.h knumber_priv.h + +include ../../admin/Doxyfile.am diff --git a/kcalc/knumber/configure.in.in b/kcalc/knumber/configure.in.in new file mode 100644 index 0000000..8ef670b --- /dev/null +++ b/kcalc/knumber/configure.in.in @@ -0,0 +1,73 @@ +AC_DEFUN([KDE_C_LONG_DOUBLE], +[ + AC_CACHE_CHECK(for long double, ac_cv_c_long_double, + [ + ac_save_LIBS="$LIBS" + LIBS="-lm $LIBS" + AC_TRY_RUN( + [ +#define _ISOC99_SOURCE 1 +#define _GNU_SOURCE 1 +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +int main() { +/* The Stardent Vistra knows sizeof(long double), but does not support it. */ +long double foo = 1.0; +char buffer[10]; +/* On Ultrix 4.3 cc, long double is 4 and double is 8. */ +int result = (sizeof(long double) <= sizeof(double)); +/* the following is needed for a broken printf in glibc2 */ +if (!result) { + foo = foo * 3; + sprintf(buffer,"%0.0Lf",foo); + result = strcmp(buffer, "3"); +/* and now something mean ;-) */ + foo = powl(fabsl(foo), 1); +} +exit(result); } + ], + ac_cv_c_long_double=yes, ac_cv_c_long_double=no, + ac_cv_c_long_double=no + ) + LIBS="$ac_save_LIBS" + ]) + if test $ac_cv_c_long_double = yes; then + AC_DEFINE(HAVE_LONG_DOUBLE, 1, [Define if you have support for long double in printf]) + fi +]) +KDE_C_LONG_DOUBLE + +have_l_funcs=yes +AC_CHECK_LIB(m, sqrtl,,have_l_funcs=no) + +if test "xyes" = "x$have_l_funcs" ; then + AC_DEFINE(HAVE_L_FUNCS,1,[Define if you have *l math functions (absl, ...)]) +fi + +LIBGMP= +KDE_CHECK_HEADER([gmp.h], [ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + + kde_save_LIBS=$LIBS + LIBS="$all_libraries -lgmp" + AC_TRY_LINK(dnl + [ + #include <gmp.h> + ], + [ + mpz_t _mpz; + mpz_init_set_si(_mpz, 0); + ], + [LIBGMP="-lgmp"], + [ + DO_NOT_COMPILE="$DO_NOT_COMPILE kcalc" + ]) + LIBS=$kde_save_LIBS + AC_LANG_RESTORE + +]) +AC_SUBST(LIBGMP) diff --git a/kcalc/knumber/knumber.cpp b/kcalc/knumber/knumber.cpp new file mode 100644 index 0000000..d282b26 --- /dev/null +++ b/kcalc/knumber/knumber.cpp @@ -0,0 +1,693 @@ +// -*- c-basic-offset: 2 -*- +/* This file is part of the KDE libraries + Copyright (c) 2005 Klaus Niederkrueger <kniederk@math.uni-koeln.de> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <math.h> + +#include <config.h> + +#include <qregexp.h> +#include <qstring.h> + +#include "knumber.h" + +KNumber const KNumber::Zero(0); +KNumber const KNumber::One(1); +KNumber const KNumber::MinusOne(-1); +KNumber const KNumber::Pi("3.141592653589793238462643383279502884197169" + "39937510582097494459230781640628620899862803" + "4825342117068"); +KNumber const KNumber::Euler("2.718281828459045235360287471352662497757" + "24709369995957496696762772407663035354759" + "4571382178525166427"); +KNumber const KNumber::NotDefined("nan"); + +bool KNumber::_float_output = false; +bool KNumber::_fraction_input = false; +bool KNumber::_splitoffinteger_output = false; + +KNumber::KNumber(signed int num) +{ + _num = new _knuminteger(num); +} + +KNumber::KNumber(unsigned int num) +{ + _num = new _knuminteger(num); +} + +KNumber::KNumber(signed long int num) +{ + _num = new _knuminteger(num); +} + +KNumber::KNumber(unsigned long int num) +{ + _num = new _knuminteger(num); +} + +KNumber::KNumber(unsigned long long int num) +{ + _num = new _knuminteger(num); +} + +KNumber::KNumber(double num) +{ + if ( isinf(num) ) _num = new _knumerror( _knumber::Infinity ); + else if ( isnan(num) ) _num = new _knumerror( _knumber::UndefinedNumber ); + else _num = new _knumfloat(num); + +} + +KNumber::KNumber(KNumber const & num) +{ + switch(num.type()) { + case SpecialType: + _num = new _knumerror(*(num._num)); + return; + case IntegerType: + _num = new _knuminteger(*(num._num)); + return; + case FractionType: + _num = new _knumfraction(*(num._num)); + return; + case FloatType: + _num = new _knumfloat(*(num._num)); + return; + }; +} + + +KNumber::KNumber(QString const & num) +{ + if (QRegExp("^(inf|-inf|nan)$").exactMatch(num)) + _num = new _knumerror(num); + else if (QRegExp("^[+-]?\\d+$").exactMatch(num)) + _num = new _knuminteger(num); + else if (QRegExp("^[+-]?\\d+/\\d+$").exactMatch(num)) { + _num = new _knumfraction(num); + simplifyRational(); + } + else if (QRegExp("^[+-]?\\d+(\\.\\d*)?(e[+-]?\\d+)?$").exactMatch(num)) + if (_fraction_input == true) { + _num = new _knumfraction(num); + simplifyRational(); + } else + _num = new _knumfloat(num); + else + _num = new _knumerror("nan"); +} + +KNumber::NumType KNumber::type(void) const +{ + if(dynamic_cast<_knumerror *>(_num)) + return SpecialType; + if(dynamic_cast<_knuminteger *>(_num)) + return IntegerType; + if(dynamic_cast<_knumfraction *>(_num)) + return FractionType; + if(dynamic_cast<_knumfloat *>(_num)) + return FloatType; + + return SpecialType; +} + +// This method converts a fraction to an integer, whenever possible, +// i.e. 5/1 --> 5 +// This method should be called, whenever such a inproper fraction can occur, +// e.g. when adding 4/3 + 2/3.... +void KNumber::simplifyRational(void) +{ + if (type() != FractionType) + return; + + _knumfraction *tmp_num = dynamic_cast<_knumfraction *>(_num); + + if (tmp_num->isInteger()) { + _knumber *tmp_num2 = tmp_num->intPart(); + delete tmp_num; + _num = tmp_num2; + } + +} + + +KNumber const & KNumber::operator=(KNumber const & num) +{ + if (this == & num) + return *this; + + delete _num; + + switch(num.type()) { + case SpecialType: + _num = new _knumerror(); + break; + case IntegerType: + _num = new _knuminteger(); + break; + case FractionType: + _num = new _knumfraction(); + break; + case FloatType: + _num = new _knumfloat(); + break; + }; + + _num->copy(*(num._num)); + + return *this; +} + +KNumber & KNumber::operator +=(KNumber const &arg) +{ + KNumber tmp_num = *this + arg; + + delete _num; + + switch(tmp_num.type()) { + case SpecialType: + _num = new _knumerror(); + break; + case IntegerType: + _num = new _knuminteger(); + break; + case FractionType: + _num = new _knumfraction(); + break; + case FloatType: + _num = new _knumfloat(); + break; + }; + + _num->copy(*(tmp_num._num)); + + return *this; +} + +KNumber & KNumber::operator -=(KNumber const &arg) +{ + KNumber tmp_num = *this - arg; + + delete _num; + + switch(tmp_num.type()) { + case SpecialType: + _num = new _knumerror(); + break; + case IntegerType: + _num = new _knuminteger(); + break; + case FractionType: + _num = new _knumfraction(); + break; + case FloatType: + _num = new _knumfloat(); + break; + }; + + _num->copy(*(tmp_num._num)); + + return *this; +} + +// increase the digit at 'position' by one +static void _inc_by_one(QString &str, int position) +{ + for (int i = position; i >= 0; i--) + { + char last_char = str[i].latin1(); + switch(last_char) + { + case '0': + str[i] = '1'; + break; + case '1': + str[i] = '2'; + break; + case '2': + str[i] = '3'; + break; + case '3': + str[i] = '4'; + break; + case '4': + str[i] = '5'; + break; + case '5': + str[i] = '6'; + break; + case '6': + str[i] = '7'; + break; + case '7': + str[i] = '8'; + break; + case '8': + str[i] = '9'; + break; + case '9': + str[i] = '0'; + if (i == 0) str.prepend('1'); + continue; + case '.': + continue; + } + break; + } +} + +// Cut off if more digits in fractional part than 'precision' +static void _round(QString &str, int precision) +{ + int decimalSymbolPos = str.find('.'); + + if (decimalSymbolPos == -1) + if (precision == 0) return; + else if (precision > 0) // add dot if missing (and needed) + { + str.append('.'); + decimalSymbolPos = str.length() - 1; + } + + // fill up with more than enough zeroes (in case fractional part too short) + str.append(QString().fill('0', precision)); + + // Now decide whether to round up or down + char last_char = str[decimalSymbolPos + precision + 1].latin1(); + 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 + _inc_by_one(str, decimalSymbolPos + precision); + break; + default: + break; + } + + decimalSymbolPos = str.find('.'); + str.truncate(decimalSymbolPos + precision + 1); + + // if precision == 0 delete also '.' + if (precision == 0) str = str.section('.', 0, 0); +} + +static QString roundNumber(const QString &numStr, int precision) +{ + QString tmpString = numStr; + if (precision < 0 || + ! QRegExp("^[+-]?\\d+(\\.\\d+)*(e[+-]?\\d+)?$").exactMatch(tmpString)) + return numStr; + + + // Skip the sign (for now) + bool neg = (tmpString[0] == '-'); + if (neg || tmpString[0] == '+') tmpString.remove(0, 1); + + + // Split off exponential part (including 'e'-symbol) + QString mantString = tmpString.section('e', 0, 0, + QString::SectionCaseInsensitiveSeps); + QString expString = tmpString.section('e', 1, 1, + QString::SectionCaseInsensitiveSeps | + QString::SectionIncludeLeadingSep); + if (expString.length() == 1) expString = QString(); + + + _round(mantString, precision); + + if(neg) mantString.prepend('-'); + + return mantString + expString; +} + + +QString const KNumber::toQString(int width, int prec) const +{ + QString tmp_str; + + if (*this == Zero) // important to avoid infinite loops below + return "0"; + switch (type()) { + case IntegerType: + if (width > 0) { //result needs to be cut-off + bool tmp_bool = _fraction_input; // stupid work-around + _fraction_input = false; + tmp_str = (KNumber("1.0")*(*this)).toQString(width, -1); + _fraction_input = tmp_bool; + } else + tmp_str = QString(_num->ascii()); + break; + case FractionType: + if (_float_output) { + bool tmp_bool = _fraction_input; // stupid work-around + _fraction_input = false; + tmp_str = (KNumber("1.0")*(*this)).toQString(width, -1); + _fraction_input = tmp_bool; + } else { // _float_output == false + if(_splitoffinteger_output) { + // split off integer part + KNumber int_part = this->integerPart(); + if (int_part == Zero) + tmp_str = QString(_num->ascii()); + else if (int_part < Zero) + tmp_str = int_part.toQString() + " " + (int_part - *this)._num->ascii(); + else + tmp_str = int_part.toQString() + " " + (*this - int_part)._num->ascii(); + } else + tmp_str = QString(_num->ascii()); + + if (width > 0 && tmp_str.length() > width) { + //result needs to be cut-off + bool tmp_bool = _fraction_input; // stupid work-around + _fraction_input = false; + tmp_str = (KNumber("1.0")*(*this)).toQString(width, -1); + _fraction_input = tmp_bool; + } + } + + break; + case FloatType: + if (width > 0) + tmp_str = QString(_num->ascii(width)); + else + // rough estimate for maximal decimal precision (10^3 = 2^10) + tmp_str = QString(_num->ascii(3*mpf_get_default_prec()/10)); + break; + default: + return QString(_num->ascii()); + } + + if (prec >= 0) + return roundNumber(tmp_str, prec); + else + return tmp_str; +} + +void KNumber::setDefaultFloatOutput(bool flag) +{ + _float_output = flag; +} + +void KNumber::setDefaultFractionalInput(bool flag) +{ + _fraction_input = flag; +} + +void KNumber::setSplitoffIntegerForFractionOutput(bool flag) +{ + _splitoffinteger_output = flag; +} + +void KNumber::setDefaultFloatPrecision(unsigned int prec) +{ + // Need to transform decimal digits into binary digits + unsigned long int bin_prec = static_cast<unsigned long int> + (double(prec) * M_LN10 / M_LN2 + 1); + + mpf_set_default_prec(bin_prec); +} + +KNumber const KNumber::abs(void) const +{ + KNumber tmp_num; + delete tmp_num._num; + + tmp_num._num = _num->abs(); + + return tmp_num; +} + +KNumber const KNumber::cbrt(void) const +{ + KNumber tmp_num; + delete tmp_num._num; + + tmp_num._num = _num->cbrt(); + + return tmp_num; +} + +KNumber const KNumber::sqrt(void) const +{ + KNumber tmp_num; + delete tmp_num._num; + + tmp_num._num = _num->sqrt(); + + return tmp_num; +} + +KNumber const KNumber::integerPart(void) const +{ + KNumber tmp_num; + delete tmp_num._num; + tmp_num._num = _num->intPart(); + + return tmp_num; +} + +KNumber const KNumber::power(KNumber const &exp) const +{ + if (*this == Zero) { + if(exp == Zero) + return KNumber("nan"); // 0^0 not defined + else if (exp < Zero) + return KNumber("inf"); + else + return KNumber(0); + } + + if (exp == Zero) { + if (*this != Zero) + return One; + else + return KNumber("nan"); + } + else if (exp < Zero) { + KNumber tmp_num; + KNumber tmp_num2 = -exp; + delete tmp_num._num; + tmp_num._num = _num->power(*(tmp_num2._num)); + + return One/tmp_num; + } + else { + KNumber tmp_num; + delete tmp_num._num; + tmp_num._num = _num->power(*(exp._num)); + + return tmp_num; + } + +} + +KNumber const KNumber::operator-(void) const +{ + KNumber tmp_num; + delete tmp_num._num; + + tmp_num._num = _num->change_sign(); + + return tmp_num; +} + +KNumber const KNumber::operator+(KNumber const & arg2) const +{ + KNumber tmp_num; + delete tmp_num._num; + + tmp_num._num = _num->add(*arg2._num); + + tmp_num.simplifyRational(); + + return tmp_num; +} + +KNumber const KNumber::operator-(KNumber const & arg2) const +{ + return *this + (-arg2); +} + +KNumber const KNumber::operator*(KNumber const & arg2) const +{ + KNumber tmp_num; + delete tmp_num._num; + + tmp_num._num = _num->multiply(*arg2._num); + + tmp_num.simplifyRational(); + + return tmp_num; +} + +KNumber const KNumber::operator/(KNumber const & arg2) const +{ + KNumber tmp_num; + delete tmp_num._num; + + tmp_num._num = _num->divide(*arg2._num); + + tmp_num.simplifyRational(); + + return tmp_num; +} + + +KNumber const KNumber::operator%(KNumber const & arg2) const +{ + if (type() != IntegerType || arg2.type() != IntegerType) + return Zero; + + KNumber tmp_num; + delete tmp_num._num; + + _knuminteger const *tmp_arg1 = dynamic_cast<_knuminteger const *>(_num); + _knuminteger const *tmp_arg2 = dynamic_cast<_knuminteger const *>(arg2._num); + + tmp_num._num = tmp_arg1->mod(*tmp_arg2); + + return tmp_num; +} + +KNumber const KNumber::operator&(KNumber const & arg2) const +{ + if (type() != IntegerType || arg2.type() != IntegerType) + return Zero; + + KNumber tmp_num; + delete tmp_num._num; + + _knuminteger const *tmp_arg1 = dynamic_cast<_knuminteger const *>(_num); + _knuminteger const *tmp_arg2 = dynamic_cast<_knuminteger const *>(arg2._num); + + tmp_num._num = tmp_arg1->intAnd(*tmp_arg2); + + return tmp_num; + +} + +KNumber const KNumber::operator|(KNumber const & arg2) const +{ + if (type() != IntegerType || arg2.type() != IntegerType) + return Zero; + + KNumber tmp_num; + delete tmp_num._num; + + _knuminteger const *tmp_arg1 = dynamic_cast<_knuminteger const *>(_num); + _knuminteger const *tmp_arg2 = dynamic_cast<_knuminteger const *>(arg2._num); + + tmp_num._num = tmp_arg1->intOr(*tmp_arg2); + + return tmp_num; +} + + +KNumber const KNumber::operator<<(KNumber const & arg2) const +{ + if (type() != IntegerType || arg2.type() != IntegerType) + return KNumber("nan"); + + _knuminteger const *tmp_arg1 = dynamic_cast<_knuminteger const *>(_num); + _knuminteger const *tmp_arg2 = dynamic_cast<_knuminteger const *>(arg2._num); + + KNumber tmp_num; + delete tmp_num._num; + tmp_num._num = tmp_arg1->shift(*tmp_arg2); + + return tmp_num; +} + +KNumber const KNumber::operator>>(KNumber const & arg2) const +{ + if (type() != IntegerType || arg2.type() != IntegerType) + return KNumber("nan"); + + KNumber tmp_num = -arg2; + + _knuminteger const *tmp_arg1 = dynamic_cast<_knuminteger const *>(_num); + _knuminteger const *tmp_arg2 = dynamic_cast<_knuminteger const *>(tmp_num._num); + + KNumber tmp_num2; + delete tmp_num2._num; + tmp_num2._num = tmp_arg1->shift(*tmp_arg2); + + return tmp_num2; +} + + + +KNumber::operator bool(void) const +{ + if (*this == Zero) + return false; + return true; +} + +KNumber::operator signed long int(void) const +{ + return static_cast<signed long int>(*_num); +} + +KNumber::operator unsigned long int(void) const +{ + return static_cast<unsigned long int>(*_num); +} + +KNumber::operator unsigned long long int(void) const +{ +#if SIZEOF_UNSIGNED_LONG == 8 + return static_cast<unsigned long int>(*this); +#elif SIZEOF_UNSIGNED_LONG == 4 + KNumber tmp_num1 = this->abs().integerPart(); + unsigned long long int tmp_num2 = static_cast<unsigned long int>(tmp_num1) + + (static_cast<unsigned long long int>( + static_cast<unsigned long int>(tmp_num1 >> KNumber("32"))) << 32) ; + +#warning the cast operator from KNumber to unsigned long long int is probably buggy, when a sign is involved + if (*this > KNumber(0)) + return tmp_num2; + else + return static_cast<unsigned long long int> (- static_cast<signed long long int>(tmp_num2)); +#else +#error "SIZEOF_UNSIGNED_LONG is a unhandled case" +#endif +} + +KNumber::operator double(void) const +{ + return static_cast<double>(*_num); +} + +int const KNumber::compare(KNumber const & arg2) const +{ + return _num->compare(*arg2._num); +} diff --git a/kcalc/knumber/knumber.h b/kcalc/knumber/knumber.h new file mode 100644 index 0000000..489a579 --- /dev/null +++ b/kcalc/knumber/knumber.h @@ -0,0 +1,289 @@ +// -*- c-basic-offset: 2 -*- +/* This file is part of the KDE libraries + Copyright (C) 2005 Klaus Niederkrueger <kniederk@math.uni-koeln.de> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef _KNUMBER_H +#define _KNUMBER_H + +#include <kdelibs_export.h> + +#include "knumber_priv.h" + +class QString; + +/** + * + * @short Class that provides arbitrary precision numbers + * + * KNumber provides access to arbitrary precision numbers from within + * KDE. + * + * KNumber is based on the GMP (GNU Multiprecision) library and + * provides transparent support to integer, fractional and floating + * point number. It contains rudimentary error handling, and also + * includes methods for converting the numbers to QStrings for + * output, and to read QStrings to obtain a KNumber. + * + * The different types of numbers that can be represented by objects + * of this class will be described below: + * + * @li @p NumType::SpecialType - This type represents an error that + * has occurred, e.g. trying to divide 1 by 0 gives an object that + * represents infinity. + * + * @li @p NumType::IntegerType - The number is an integer. It can be + * arbitrarily large (restricted by the memory of the system). + * + * @li @p NumType::FractionType - A fraction is a number of the form + * denominator divided by nominator, where both denominator and + * nominator are integers of arbitrary size. + * + * @li @p NumType::FloatType - The number is of floating point + * type. These numbers are usually rounded, so that they do not + * represent precise values. + * + * + * @author Klaus Niederkrueger <kniederk@math.uni-koeln.de> + */ +class KDE_EXPORT KNumber +{ + public: + static KNumber const Zero; + static KNumber const One; + static KNumber const MinusOne; + static KNumber const Pi; + static KNumber const Euler; + static KNumber const NotDefined; + + /** + * KNumber tries to provide transparent access to the following type + * of numbers: + * + * @li @p NumType::SpecialType - Some type of error has occurred, + * further inspection with @p KNumber::ErrorType + * + * @li @p NumType::IntegerType - the number is an integer + * + * @li @p NumType::FractionType - the number is a fraction + * + * @li @p NumType::FloatType - the number is of floating point type + * + */ + enum NumType {SpecialType, IntegerType, FractionType, FloatType}; + + /** + * A KNumber that represents an error, i.e. that is of type @p + * NumType::SpecialType can further distinguished: + * + * @li @p ErrorType::UndefinedNumber - This is e.g. the result of + * taking the square root of a negative number or computing + * \f$ \infty - \infty \f$. + * + * @li @p ErrorType::Infinity - Such a number can be e.g. obtained + * by dividing 1 by 0. Some further calculations are still allowed, + * e.g. \f$ \infty + 5 \f$ still gives \f$\infty\f$. + * + * @li @p ErrorType::MinusInfinity - MinusInfinity behaves similarly + * to infinity above. It can be obtained by changing the sign of + * infinity. + * + */ + enum ErrorType {UndefinedNumber, Infinity, MinusInfinity}; + + KNumber(signed int num = 0); + KNumber(unsigned int num); + KNumber(signed long int num); + KNumber(unsigned long int num); + KNumber(unsigned long long int num); + + KNumber(double num); + + KNumber(KNumber const & num); + + KNumber(QString const & num); + + ~KNumber() + { + delete _num; + } + + KNumber const & operator=(KNumber const & num); + + /** + * Returns the type of the number, as explained in @p KNumber::NumType. + */ + NumType type(void) const; + + /** + * Set whether the output of numbers (with KNumber::toQString) + * should happen as floating point numbers or not. This method has + * in fact only an effect on numbers of type @p + * NumType::FractionType, which can be either displayed as fractions + * or in decimal notation. + * + * The default behavior is not to display fractions in floating + * point notation. + */ + static void setDefaultFloatOutput(bool flag); + + /** + * Set whether a number constructed from a QString should be + * initialized as a fraction or as a float, e.g. "1.01" would be + * treated as 101/100, if this flag is set to true. + * + * The default setting is false. + */ + static void setDefaultFractionalInput(bool flag); + + /** + * Set the default precision to be *at least* @p prec (decimal) + * digits. All subsequent initialized floats will use at least this + * precision, but previously initialized variables are unaffected. + */ + static void setDefaultFloatPrecision(unsigned int prec); + + /** + * What a terrible method name!! When displaying a fraction, the + * default mode gives @p "nomin/denom". With this method one can + * choose to display a fraction as @p "integer nomin/denom". + * + * Examples: Default representation mode is 47/17, but if @p flag is + * @p true, then the result is 2 13/17. + */ + static void setSplitoffIntegerForFractionOutput(bool flag); + + /** + * Return a QString representing the KNumber. + * + * @param width This number specifies the maximal length of the + * output, before the method switches to exponential notation and + * does rounding. For negative numbers, this option is ignored. + * + * @param prec This parameter controls the number of digits + * following the decimal point. For negative numbers, this option + * is ignored. + * + */ + QString const toQString(int width = -1, int prec = -1) const; + + /** + * Compute the absolute value, i.e. @p x.abs() returns the value + * + * \f[ \left\{\begin{array}{cl} x, & x \ge 0 \\ -x, & x < + * 0\end{array}\right.\f] + * This method works for \f$ x = \infty \f$ and \f$ x = -\infty \f$. + */ + KNumber const abs(void) const; + + /** + * Compute the square root. If \f$ x < 0 \f$ (including \f$ + * x=-\infty \f$), then @p x.sqrt() returns @p + * ErrorType::UndefinedNumber. + * + * If @p x is an integer or a fraction, then @p x.sqrt() tries to + * compute the exact square root. If the square root is not a + * fraction, then a float with the default precision is returned. + * + * This method works for \f$ x = \infty \f$ giving \f$ \infty \f$. + */ + KNumber const sqrt(void) const; + + /** + * Compute the cube root. + * + * If @p x is an integer or a fraction, then @p x.cbrt() tries to + * compute the exact cube root. If the cube root is not a fraction, + * then a float is returned, but + * + * WARNING: A float cube root is computed as a standard @p double + * that is later transformed back into a @p KNumber. + * + * This method works for \f$ x = \infty \f$ giving \f$ \infty \f$, + * and for \f$ x = -\infty \f$ giving \f$ -\infty \f$. + */ + KNumber const cbrt(void) const; + + /** + * Truncates a @p KNumber to its integer type returning a number of + * type @p NumType::IntegerType. + * + * If \f$ x = \pm\infty \f$, integerPart leaves the value unchanged, + * i.e. it returns \f$ \pm\infty \f$. + */ + KNumber const integerPart(void) const; + + KNumber const power(KNumber const &exp) const; + + KNumber const operator+(KNumber const & arg2) const; + KNumber const operator -(void) const; + KNumber const operator-(KNumber const & arg2) const; + KNumber const operator*(KNumber const & arg2) const; + KNumber const operator/(KNumber const & arg2) const; + KNumber const operator%(KNumber const & arg2) const; + + KNumber const operator&(KNumber const & arg2) const; + KNumber const operator|(KNumber const & arg2) const; + KNumber const operator<<(KNumber const & arg2) const; + KNumber const operator>>(KNumber const & arg2) const; + + operator bool(void) const; + operator signed long int(void) const; + operator unsigned long int(void) const; + operator unsigned long long int(void) const; + operator double(void) const; + + bool const operator==(KNumber const & arg2) const + { return (compare(arg2) == 0); } + + bool const operator!=(KNumber const & arg2) const + { return (compare(arg2) != 0); } + + bool const operator>(KNumber const & arg2) const + { return (compare(arg2) > 0); } + + bool const operator<(KNumber const & arg2) const + { return (compare(arg2) < 0); } + + bool const operator>=(KNumber const & arg2) const + { return (compare(arg2) >= 0); } + + bool const operator<=(KNumber const & arg2) const + { return (compare(arg2) <= 0); } + + KNumber & operator +=(KNumber const &arg); + KNumber & operator -=(KNumber const &arg); + + + //KNumber const toFloat(void) const; + + + + + private: + void simplifyRational(void); + int const compare(KNumber const & arg2) const; + + _knumber *_num; + static bool _float_output; + static bool _fraction_input; + static bool _splitoffinteger_output; +}; + + + +#endif // _KNUMBER_H diff --git a/kcalc/knumber/knumber_priv.cpp b/kcalc/knumber/knumber_priv.cpp new file mode 100644 index 0000000..1326d44 --- /dev/null +++ b/kcalc/knumber/knumber_priv.cpp @@ -0,0 +1,1083 @@ +/* This file is part of the KDE libraries + Copyright (c) 2005 Klaus Niederkrueger <kniederk@math.uni-koeln.de> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <math.h> +#include <config.h> + +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#include <qregexp.h> +#include <qstring.h> + +#include "knumber_priv.h" + +_knumerror::_knumerror(_knumber const & num) +{ + switch(num.type()) { + case SpecialType: + _error = dynamic_cast<_knumerror const &>(num)._error; + break; + case IntegerType: + case FractionType: + case FloatType: + // What should I do here? + break; + } +} + + + +_knuminteger::_knuminteger(unsigned long long int num) +{ + mpz_init(_mpz); +#if SIZEOF_UNSIGNED_LONG == 8 + mpz_init_set_ui(_mpz, static_cast<unsigned long int>(num)); +#elif SIZEOF_UNSIGNED_LONG == 4 + mpz_set_ui(_mpz, static_cast<unsigned long int>(num >> 32)); + mpz_mul_2exp(_mpz, _mpz, 32); + mpz_add_ui(_mpz, _mpz, static_cast<unsigned long int>(num)); +#else +#error "SIZEOF_UNSIGNED_LONG is a unhandled case" +#endif +} + + +_knuminteger::_knuminteger(_knumber const & num) +{ + mpz_init(_mpz); + + switch(num.type()) { + case IntegerType: + mpz_set(_mpz, dynamic_cast<_knuminteger const &>(num)._mpz); + break; + case FractionType: + case FloatType: + case SpecialType: + // What should I do here? + break; + } +} + +_knumfraction::_knumfraction(_knumber const & num) +{ + mpq_init(_mpq); + + switch(num.type()) { + case IntegerType: + mpq_set_z(_mpq, dynamic_cast<_knuminteger const &>(num)._mpz); + break; + case FractionType: + mpq_set(_mpq, dynamic_cast<_knumfraction const &>(num)._mpq); + break; + case FloatType: + case SpecialType: + // What should I do here? + break; + } +} + +_knumfloat::_knumfloat(_knumber const & num) +{ + mpf_init(_mpf); + + switch(num.type()) { + case IntegerType: + mpf_set_z(_mpf, dynamic_cast<_knuminteger const &>(num)._mpz); + break; + case FractionType: + mpf_set_q(_mpf, dynamic_cast<_knumfraction const &>(num)._mpq); + break; + case FloatType: + mpf_set(_mpf, dynamic_cast<_knumfloat const &>(num)._mpf); + break; + case SpecialType: + // What should I do here? + break; + } +} + + + +_knumerror::_knumerror(QString const & num) +{ + if (num == "nan") + _error = UndefinedNumber; + else if (num == "inf") + _error = Infinity; + else if (num == "-inf") + _error = MinusInfinity; +} + +_knuminteger::_knuminteger(QString const & num) +{ + mpz_init(_mpz); + mpz_set_str(_mpz, num.ascii(), 10); +} + +_knumfraction::_knumfraction(QString const & num) +{ + mpq_init(_mpq); + if (QRegExp("^[+-]?\\d+(\\.\\d*)?(e[+-]?\\d+)?$").exactMatch(num)) { + // my hand-made conversion is terrible + // first me convert the mantissa + unsigned long int digits_after_dot = ((num.section( '.', 1, 1)).section('e', 0, 0)).length(); + QString tmp_num = num.section('e', 0, 0).remove('.'); + mpq_set_str(_mpq, tmp_num.ascii(), 10); + mpz_t tmp_int; + mpz_init(tmp_int); + mpz_ui_pow_ui (tmp_int, 10, digits_after_dot); + mpz_mul(mpq_denref(_mpq), mpq_denref(_mpq), tmp_int); + // now we take care of the exponent + if (! (tmp_num = num.section('e', 1, 1)).isEmpty()) { + long int tmp_exp = tmp_num.toLong(); + if (tmp_exp > 0) { + mpz_ui_pow_ui (tmp_int, 10, + static_cast<unsigned long int>(tmp_exp)); + mpz_mul(mpq_numref(_mpq), mpq_numref(_mpq), tmp_int); + } else { + mpz_ui_pow_ui (tmp_int, 10, + static_cast<unsigned long int>(-tmp_exp)); + mpz_mul(mpq_denref(_mpq), mpq_denref(_mpq), tmp_int); + } + } + mpz_clear(tmp_int); + } else + mpq_set_str(_mpq, num.ascii(), 10); + mpq_canonicalize(_mpq); +} + +_knumfloat::_knumfloat(QString const & num) +{ + mpf_init(_mpf); + mpf_set_str(_mpf, num.ascii(), 10); +} + +_knuminteger const & _knuminteger::operator = (_knuminteger const & num) +{ + if (this == &num) + return *this; + + mpz_set(_mpz, num._mpz); + return *this; +} + +QString const _knumerror::ascii(int prec) const +{ + static_cast<void>(prec); + + switch(_error) { + case UndefinedNumber: + return QString("nan"); + case Infinity: + return QString("inf"); + case MinusInfinity: + return QString("-inf"); + default: + return QString::null; + } +} + +QString const _knuminteger::ascii(int prec) const +{ + static_cast<void>(prec); + char *tmp_ptr; + + gmp_asprintf(&tmp_ptr, "%Zd", _mpz); + QString ret_str = tmp_ptr; + + free(tmp_ptr); + return ret_str; +} + +QString const _knumfraction::ascii(int prec) const +{ + static_cast<void>(prec); + char *tmp_ptr = mpq_get_str(0, 10, _mpq); + QString ret_str = tmp_ptr; + + free(tmp_ptr); + + return ret_str; +} + +QString const _knumfloat::ascii(int prec) const +{ + QString ret_str; + char *tmp_ptr; + if (prec > 0) + gmp_asprintf(&tmp_ptr, ("%." + QString().setNum(prec) + "Fg").ascii(), _mpf); + else + gmp_asprintf(&tmp_ptr, "%Fg", _mpf); + + ret_str = tmp_ptr; + + free(tmp_ptr); + + return ret_str; +} + + +bool _knumfraction::isInteger(void) const +{ + if (mpz_cmp_ui(mpq_denref(_mpq), 1) == 0) + return true; + else + return false; +} + + +_knumber * _knumerror::abs(void) const +{ + _knumerror * tmp_num = new _knumerror(*this); + + if(_error == MinusInfinity) tmp_num->_error = Infinity; + + return tmp_num; +} + +_knumber * _knuminteger::abs(void) const +{ + _knuminteger * tmp_num = new _knuminteger(); + + mpz_abs(tmp_num->_mpz, _mpz); + + return tmp_num; +} + +_knumber * _knumfraction::abs(void) const +{ + _knumfraction * tmp_num = new _knumfraction(); + + mpq_abs(tmp_num->_mpq, _mpq); + + return tmp_num; +} + +_knumber * _knumfloat::abs(void) const +{ + _knumfloat * tmp_num = new _knumfloat(); + + mpf_abs(tmp_num->_mpf, _mpf); + + return tmp_num; +} + + + +_knumber * _knumerror::intPart(void) const +{ + return new _knumerror(*this); +} + +_knumber * _knuminteger::intPart(void) const +{ + _knuminteger *tmp_num = new _knuminteger(); + mpz_set(tmp_num->_mpz, _mpz); + return tmp_num; +} + +_knumber * _knumfraction::intPart(void) const +{ + _knuminteger *tmp_num = new _knuminteger(); + + mpz_set_q(tmp_num->_mpz, _mpq); + + return tmp_num; +} + +_knumber * _knumfloat::intPart(void) const +{ + _knuminteger *tmp_num = new _knuminteger(); + + mpz_set_f(tmp_num->_mpz, _mpf); + + return tmp_num; +} + + + + +int _knumerror::sign(void) const +{ + switch(_error) { + case Infinity: + return 1; + case MinusInfinity: + return -1; + default: + return 0; + } +} + +int _knuminteger::sign(void) const +{ + return mpz_sgn(_mpz); +} + +int _knumfraction::sign(void) const +{ + return mpq_sgn(_mpq); +} + +int _knumfloat::sign(void) const +{ + return mpf_sgn(_mpf); +} + + + +#warning _cbrt for now this is a stupid work around +static void _cbrt(mpf_t &num) +{ + double tmp_num = cbrt(mpf_get_d(num)); + mpf_init_set_d(num, tmp_num); +} + + +_knumber * _knumerror::cbrt(void) const +{ + // infty ^3 = infty; -infty^3 = -infty + _knumerror *tmp_num = new _knumerror(*this); + + return tmp_num; +} + +_knumber * _knuminteger::cbrt(void) const +{ + _knuminteger * tmp_num = new _knuminteger(); + + if(mpz_root(tmp_num->_mpz, _mpz, 3)) + return tmp_num; // root is perfect + + delete tmp_num; // root was not perfect, result will be float + + _knumfloat * tmp_num2 = new _knumfloat(); + mpf_set_z(tmp_num2->_mpf, _mpz); + + _cbrt(tmp_num2->_mpf); + + return tmp_num2; +} + +_knumber * _knumfraction::cbrt(void) const +{ + _knumfraction * tmp_num = new _knumfraction(); + if (mpz_root(mpq_numref(tmp_num->_mpq), mpq_numref(_mpq), 3) + && mpz_root(mpq_denref(tmp_num->_mpq), mpq_denref(_mpq), 3)) + return tmp_num; // root is perfect + + delete tmp_num; // root was not perfect, result will be float + + _knumfloat * tmp_num2 = new _knumfloat(); + mpf_set_q(tmp_num2->_mpf, _mpq); + + _cbrt(tmp_num2->_mpf); + + return tmp_num2; +} + +_knumber * _knumfloat::cbrt(void) const +{ + _knumfloat * tmp_num = new _knumfloat(*this); + + _cbrt(tmp_num->_mpf); + + return tmp_num; +} + + + + +_knumber * _knumerror::sqrt(void) const +{ + _knumerror *tmp_num = new _knumerror(*this); + + if(_error == MinusInfinity) tmp_num->_error = UndefinedNumber; + + return tmp_num; +} + +_knumber * _knuminteger::sqrt(void) const +{ + if (mpz_sgn(_mpz) < 0) { + _knumerror *tmp_num = new _knumerror(UndefinedNumber); + return tmp_num; + } + if (mpz_perfect_square_p(_mpz)) { + _knuminteger * tmp_num = new _knuminteger(); + + mpz_sqrt(tmp_num->_mpz, _mpz); + + return tmp_num; + } else { + _knumfloat * tmp_num = new _knumfloat(); + mpf_set_z(tmp_num->_mpf, _mpz); + mpf_sqrt(tmp_num->_mpf, tmp_num->_mpf); + + return tmp_num; + } +} + +_knumber * _knumfraction::sqrt(void) const +{ + if (mpq_sgn(_mpq) < 0) { + _knumerror *tmp_num = new _knumerror(UndefinedNumber); + return tmp_num; + } + if (mpz_perfect_square_p(mpq_numref(_mpq)) + && mpz_perfect_square_p(mpq_denref(_mpq))) { + _knumfraction * tmp_num = new _knumfraction(); + mpq_set(tmp_num->_mpq, _mpq); + mpz_sqrt(mpq_numref(tmp_num->_mpq), mpq_numref(tmp_num->_mpq)); + mpz_sqrt(mpq_denref(tmp_num->_mpq), mpq_denref(tmp_num->_mpq)); + + return tmp_num; + } else { + _knumfloat * tmp_num = new _knumfloat(); + mpf_set_q(tmp_num->_mpf, _mpq); + mpf_sqrt(tmp_num->_mpf, tmp_num->_mpf); + + return tmp_num; + } + + _knumfraction * tmp_num = new _knumfraction(); + + return tmp_num; +} + +_knumber * _knumfloat::sqrt(void) const +{ + if (mpf_sgn(_mpf) < 0) { + _knumerror *tmp_num = new _knumerror(UndefinedNumber); + return tmp_num; + } + _knumfloat * tmp_num = new _knumfloat(); + + mpf_sqrt(tmp_num->_mpf, _mpf); + + return tmp_num; +} + + + +_knumber * _knumerror::change_sign(void) const +{ + _knumerror * tmp_num = new _knumerror(); + + if(_error == Infinity) tmp_num->_error = MinusInfinity; + if(_error == MinusInfinity) tmp_num->_error = Infinity; + + return tmp_num; +} + +_knumber * _knuminteger::change_sign(void) const +{ + _knuminteger * tmp_num = new _knuminteger(); + + mpz_neg(tmp_num->_mpz, _mpz); + + return tmp_num; +} + +_knumber * _knumfraction::change_sign(void) const +{ + _knumfraction * tmp_num = new _knumfraction(); + + mpq_neg(tmp_num->_mpq, _mpq); + + return tmp_num; +} + +_knumber *_knumfloat::change_sign(void) const +{ + _knumfloat * tmp_num = new _knumfloat(); + + mpf_neg(tmp_num->_mpf, _mpf); + + return tmp_num; +} + + +_knumber * _knumerror::reciprocal(void) const +{ + switch(_error) { + case Infinity: + case MinusInfinity: + return new _knuminteger(0); + case UndefinedNumber: + default: + return new _knumerror(UndefinedNumber); + } +} + +_knumber * _knuminteger::reciprocal(void) const +{ + if(mpz_cmp_si(_mpz, 0) == 0) return new _knumerror(Infinity); + + _knumfraction * tmp_num = new _knumfraction(*this); + + mpq_inv(tmp_num->_mpq, tmp_num->_mpq); + + return tmp_num; +} + +_knumber * _knumfraction::reciprocal() const +{ + if(mpq_cmp_si(_mpq, 0, 1) == 0) return new _knumerror(Infinity); + + _knumfraction * tmp_num = new _knumfraction(); + + mpq_inv(tmp_num->_mpq, _mpq); + + return tmp_num; +} + +_knumber *_knumfloat::reciprocal(void) const +{ + if(mpf_cmp_si(_mpf, 0) == 0) return new _knumerror(Infinity); + + _knumfloat * tmp_num = new _knumfloat(); + + mpf_div(tmp_num->_mpf, _knumfloat("1.0")._mpf, _mpf); + + return tmp_num; +} + + + +_knumber * _knumerror::add(_knumber const & arg2) const +{ + if (arg2.type() != SpecialType) + return new _knumerror(_error); + + _knumerror const & tmp_arg2 = dynamic_cast<_knumerror const &>(arg2); + + if (_error == UndefinedNumber + || tmp_arg2._error == UndefinedNumber + || (_error == Infinity && tmp_arg2._error == MinusInfinity) + || (_error == MinusInfinity && tmp_arg2._error == Infinity) + ) + return new _knumerror(UndefinedNumber); + + return new _knumerror(_error); +} + +_knumber * _knuminteger::add(_knumber const & arg2) const +{ + if (arg2.type() != IntegerType) + return arg2.add(*this); + + _knuminteger * tmp_num = new _knuminteger(); + + mpz_add(tmp_num->_mpz, _mpz, + dynamic_cast<_knuminteger const &>(arg2)._mpz); + + return tmp_num; +} + +_knumber * _knumfraction::add(_knumber const & arg2) const +{ + if (arg2.type() == IntegerType) { + // need to cast arg2 to fraction + _knumfraction tmp_num(arg2); + return tmp_num.add(*this); + } + + + if (arg2.type() == FloatType || arg2.type() == SpecialType) + return arg2.add(*this); + + _knumfraction * tmp_num = new _knumfraction(); + + mpq_add(tmp_num->_mpq, _mpq, + dynamic_cast<_knumfraction const &>(arg2)._mpq); + + return tmp_num; +} + +_knumber *_knumfloat::add(_knumber const & arg2) const +{ + if (arg2.type() == SpecialType) + return arg2.add(*this); + + if (arg2.type() != FloatType) { + // need to cast arg2 to float + _knumfloat tmp_num(arg2); + return tmp_num.add(*this); + } + + _knumfloat * tmp_num = new _knumfloat(); + + mpf_add(tmp_num->_mpf, _mpf, + dynamic_cast<_knumfloat const &>(arg2)._mpf); + + return tmp_num; +} + + +_knumber * _knumerror::multiply(_knumber const & arg2) const +{ + //improve this + switch(arg2.type()) { + case SpecialType: + { + _knumerror const & tmp_arg2 = dynamic_cast<_knumerror const &>(arg2); + if (_error == UndefinedNumber || tmp_arg2._error == UndefinedNumber) + return new _knumerror(UndefinedNumber); + if ( this->sign() * arg2.sign() > 0) + return new _knumerror(Infinity); + else + return new _knumerror(MinusInfinity); + } + case IntegerType: + case FractionType: + case FloatType: + { + int sign_arg2 = arg2.sign(); + if (_error == UndefinedNumber || sign_arg2 == 0) + return new _knumerror(UndefinedNumber); + if ( (_error == Infinity && sign_arg2 > 0) || + (_error == MinusInfinity && sign_arg2 < 0) ) + return new _knumerror(Infinity); + + return new _knumerror(MinusInfinity); + } + } + + return new _knumerror(_error); +} + + +_knumber * _knuminteger::multiply(_knumber const & arg2) const +{ + if (arg2.type() != IntegerType) + return arg2.multiply(*this); + + _knuminteger * tmp_num = new _knuminteger(); + + mpz_mul(tmp_num->_mpz, _mpz, + dynamic_cast<_knuminteger const &>(arg2)._mpz); + + return tmp_num; +} + +_knumber * _knumfraction::multiply(_knumber const & arg2) const +{ + if (arg2.type() == IntegerType) { + // need to cast arg2 to fraction + _knumfraction tmp_num(arg2); + return tmp_num.multiply(*this); + } + + + if (arg2.type() == FloatType || arg2.type() == SpecialType) + return arg2.multiply(*this); + + _knumfraction * tmp_num = new _knumfraction(); + + mpq_mul(tmp_num->_mpq, _mpq, + dynamic_cast<_knumfraction const &>(arg2)._mpq); + + return tmp_num; +} + +_knumber *_knumfloat::multiply(_knumber const & arg2) const +{ + if (arg2.type() == SpecialType) + return arg2.multiply(*this); + if (arg2.type() == IntegerType && + mpz_cmp_si(dynamic_cast<_knuminteger const &>(arg2)._mpz,0) == 0) + // if arg2 == 0 return integer 0!! + return new _knuminteger(0); + + if (arg2.type() != FloatType) { + // need to cast arg2 to float + _knumfloat tmp_num(arg2); + return tmp_num.multiply(*this); + } + + _knumfloat * tmp_num = new _knumfloat(); + + mpf_mul(tmp_num->_mpf, _mpf, + dynamic_cast<_knumfloat const &>(arg2)._mpf); + + return tmp_num; +} + + + + + +_knumber * _knumber::divide(_knumber const & arg2) const +{ + _knumber * tmp_num = arg2.reciprocal(); + _knumber * rslt_num = this->multiply(*tmp_num); + + delete tmp_num; + + return rslt_num; +} + +_knumber *_knumfloat::divide(_knumber const & arg2) const +{ + if(mpf_cmp_si(_mpf, 0) == 0) return new _knumerror(Infinity); + + // automatically casts arg2 to float + _knumfloat * tmp_num = new _knumfloat(arg2); + + mpf_div(tmp_num->_mpf, _mpf, tmp_num->_mpf); + + return tmp_num; +} + + + + +_knumber * _knumerror::power(_knumber const & exponent) const +{ + static_cast<void>(exponent); + return new _knumerror(UndefinedNumber); +} + +_knumber * _knuminteger::power(_knumber const & exponent) const +{ + if (exponent.type() == IntegerType) { + + mpz_t tmp_mpz; + mpz_init_set(tmp_mpz, + dynamic_cast<_knuminteger const &>(exponent)._mpz); + + if (! mpz_fits_ulong_p(tmp_mpz)) { // conversion wouldn't work, so + // use floats + mpz_clear(tmp_mpz); + // need to cast everything to float + _knumfloat tmp_num1(*this), tmp_num2(exponent); + return tmp_num1.power(tmp_num2); + } + + unsigned long int tmp_int = mpz_get_ui(tmp_mpz); + mpz_clear(tmp_mpz); + + _knuminteger * tmp_num = new _knuminteger(); + mpz_pow_ui(tmp_num->_mpz, _mpz, tmp_int); + return tmp_num; + } + if (exponent.type() == FractionType) { + if (mpz_sgn(_mpz) < 0) + return new _knumerror(UndefinedNumber); + // GMP only supports few root functions, so we need to convert + // into signed long int + mpz_t tmp_mpz; + mpz_init_set(tmp_mpz, + mpq_denref(dynamic_cast<_knumfraction const &>(exponent)._mpq)); + + if (! mpz_fits_ulong_p(tmp_mpz)) { // conversion wouldn't work, so + // use floats + mpz_clear(tmp_mpz); + // need to cast everything to float + _knumfloat tmp_num1(*this), tmp_num2(exponent); + return tmp_num1.power(tmp_num2); + } + + unsigned long int tmp_int = mpz_get_ui(tmp_mpz); + mpz_clear(tmp_mpz); + + // first check if result will be an integer + _knuminteger * tmp_num = new _knuminteger(); + int flag = mpz_root(tmp_num->_mpz, _mpz, tmp_int); + if (flag == 0) { // result is not exact + delete tmp_num; + // need to cast everything to float + _knumfloat tmp_num1(*this), tmp_num2(exponent); + return tmp_num1.power(tmp_num2); + } + + // result is exact + + mpz_init_set(tmp_mpz, + mpq_numref(dynamic_cast<_knumfraction const &>(exponent)._mpq)); + + if (! mpz_fits_ulong_p(tmp_mpz)) { // conversion wouldn't work, so + // use floats + mpz_clear(tmp_mpz); + // need to cast everything to float + _knumfloat tmp_num1(*this), tmp_num2(exponent); + return tmp_num1.power(tmp_num2); + } + tmp_int = mpz_get_ui(tmp_mpz); + mpz_clear(tmp_mpz); + + mpz_pow_ui(tmp_num->_mpz, tmp_num->_mpz, tmp_int); + + return tmp_num; + } + if (exponent.type() == FloatType) { + // need to cast everything to float + _knumfloat tmp_num(*this); + return tmp_num.power(exponent); + } + + return new _knumerror(Infinity); +} + +_knumber * _knumfraction::power(_knumber const & exponent) const +{ + _knuminteger tmp_num = _knuminteger(); + + mpz_set(tmp_num._mpz, mpq_numref(_mpq)); + _knumber *numer = tmp_num.power(exponent); + + mpz_set(tmp_num._mpz, mpq_denref(_mpq)); + _knumber *denom = tmp_num.power(exponent); + + _knumber *result = numer->divide(*denom); + delete numer; + delete denom; + return result; +} + +_knumber * _knumfloat::power(_knumber const & exponent) const +{ + return new _knumfloat(pow(static_cast<double>(*this), + static_cast<double>(exponent))); +} + + +int _knumerror::compare(_knumber const &arg2) const +{ + if (arg2.type() != SpecialType) { + switch(_error) { + case Infinity: + return 1; + case MinusInfinity: + return -1; + default: + return 1; // Not really o.k., but what should I return + } + } + + switch(_error) { + case Infinity: + if (dynamic_cast<_knumerror const &>(arg2)._error == Infinity) + // Infinity is larger than anything else, but itself + return 0; + return 1; + case MinusInfinity: + if (dynamic_cast<_knumerror const &>(arg2)._error == MinusInfinity) + // MinusInfinity is smaller than anything else, but itself + return 0; + return -1; + default: + if (dynamic_cast<_knumerror const &>(arg2)._error == UndefinedNumber) + // Undefined only equal to itself + return 0; + return -arg2.compare(*this); + } +} + +int _knuminteger::compare(_knumber const &arg2) const +{ + if (arg2.type() != IntegerType) + return - arg2.compare(*this); + + return mpz_cmp(_mpz, dynamic_cast<_knuminteger const &>(arg2)._mpz); +} + +int _knumfraction::compare(_knumber const &arg2) const +{ + if (arg2.type() != FractionType) { + if (arg2.type() == IntegerType) { + mpq_t tmp_frac; + mpq_init(tmp_frac); + mpq_set_z(tmp_frac, + dynamic_cast<_knuminteger const &>(arg2)._mpz); + int cmp_result = mpq_cmp(_mpq, tmp_frac); + mpq_clear(tmp_frac); + return cmp_result; + } else + return - arg2.compare(*this); + } + + return mpq_cmp(_mpq, dynamic_cast<_knumfraction const &>(arg2)._mpq); +} + +int _knumfloat::compare(_knumber const &arg2) const +{ + if (arg2.type() != FloatType) { + mpf_t tmp_float; + if (arg2.type() == IntegerType) { + mpf_init(tmp_float); + mpf_set_z(tmp_float, + dynamic_cast<_knuminteger const &>(arg2)._mpz); + } else if (arg2.type() == FractionType) { + mpf_init(tmp_float); + mpf_set_q(tmp_float, + dynamic_cast<_knumfraction const &>(arg2)._mpq); + } else + return - arg2.compare(*this); + + int cmp_result = mpf_cmp(_mpf, tmp_float); + mpf_clear(tmp_float); + return cmp_result; + } + + return mpf_cmp(_mpf, dynamic_cast<_knumfloat const &>(arg2)._mpf); +} + + + +_knumerror::operator signed long int (void) const +{ + // what would be the correct return values here? + if (_error == Infinity) + return 0; + if (_error == MinusInfinity) + return 0; + else // if (_error == UndefinedNumber) + return 0; +} + +_knumerror::operator unsigned long int (void) const +{ + // what would be the correct return values here? + if (_error == Infinity) + return 0; + if (_error == MinusInfinity) + return 0; + else // if (_error == UndefinedNumber) + return 0; +} + + +_knuminteger::operator signed long int (void) const +{ + return mpz_get_si(_mpz); +} + +_knumfraction::operator signed long int (void) const +{ + return static_cast<signed long int>(mpq_get_d(_mpq)); +} + +_knumfloat::operator signed long int (void) const +{ + return mpf_get_si(_mpf); +} + +_knuminteger::operator unsigned long int (void) const +{ + return mpz_get_ui(_mpz); +} + +_knumfraction::operator unsigned long int (void) const +{ + return static_cast<unsigned long int>(mpq_get_d(_mpq)); +} + +_knumfloat::operator unsigned long int (void) const +{ + return mpf_get_ui(_mpf); +} + + + +_knumerror::operator double (void) const +{ + if (_error == Infinity) + return INFINITY; + if (_error == MinusInfinity) + return -INFINITY; + else // if (_error == UndefinedNumber) + return NAN; +} + +_knuminteger::operator double (void) const +{ + return mpz_get_d(_mpz); +} + +_knumfraction::operator double (void) const +{ + return mpq_get_d(_mpq); +} + +_knumfloat::operator double (void) const +{ + return mpf_get_d(_mpf); +} + + + + +_knuminteger * _knuminteger::intAnd(_knuminteger const &arg2) const +{ + _knuminteger * tmp_num = new _knuminteger(); + + mpz_and(tmp_num->_mpz, _mpz, arg2._mpz); + + return tmp_num; +} + +_knuminteger * _knuminteger::intOr(_knuminteger const &arg2) const +{ + _knuminteger * tmp_num = new _knuminteger(); + + mpz_ior(tmp_num->_mpz, _mpz, arg2._mpz); + + return tmp_num; +} + +_knumber * _knuminteger::mod(_knuminteger const &arg2) const +{ + if(mpz_cmp_si(arg2._mpz, 0) == 0) return new _knumerror(UndefinedNumber); + + _knuminteger * tmp_num = new _knuminteger(); + + mpz_mod(tmp_num->_mpz, _mpz, arg2._mpz); + + return tmp_num; +} + +_knumber * _knuminteger::shift(_knuminteger const &arg2) const +{ + mpz_t tmp_mpz; + + mpz_init_set (tmp_mpz, arg2._mpz); + + if (! mpz_fits_slong_p(tmp_mpz)) { + mpz_clear(tmp_mpz); + return new _knumerror(UndefinedNumber); + } + + signed long int tmp_arg2 = mpz_get_si(tmp_mpz); + mpz_clear(tmp_mpz); + + + _knuminteger * tmp_num = new _knuminteger(); + + if (tmp_arg2 > 0) // left shift + mpz_mul_2exp(tmp_num->_mpz, _mpz, tmp_arg2); + else // right shift + mpz_tdiv_q_2exp(tmp_num->_mpz, _mpz, -tmp_arg2); + + + return tmp_num; +} + diff --git a/kcalc/knumber/knumber_priv.h b/kcalc/knumber/knumber_priv.h new file mode 100644 index 0000000..7dd58a6 --- /dev/null +++ b/kcalc/knumber/knumber_priv.h @@ -0,0 +1,313 @@ +/* This file is part of the KDE libraries + Copyright (C) 2005 Klaus Niederkrueger <kniederk@math.uni-koeln.de> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef _KNUMBER_PRIV_H +#define _KNUMBER_PRIV_H + +class QString; + +#include <cstdio> +#include <gmp.h> + +// work-around for pre-C99-libs +#ifndef INFINITY +#define INFINITY HUGE_VAL +#endif +// this is really ugly +#ifndef NAN +#define NAN (atof("nan")) +#endif + +class _knumber +{ + public: + enum NumType {SpecialType, IntegerType, FractionType, FloatType}; + enum ErrorType {UndefinedNumber, Infinity, MinusInfinity}; + + _knumber() {} + + virtual ~_knumber() {} + + virtual void copy(_knumber const & num) = 0; + + virtual NumType type(void) const = 0; + + virtual QString const ascii(int prec = -1) const = 0; + + virtual _knumber * abs(void) const = 0; + virtual _knumber * intPart(void) const = 0; + virtual int sign(void) const = 0; + virtual _knumber * sqrt(void) const = 0; + virtual _knumber * cbrt(void) const = 0; + virtual _knumber * change_sign(void) const = 0; + virtual _knumber * reciprocal(void) const = 0; + virtual _knumber * add(_knumber const & arg2) const = 0; + virtual _knumber * multiply(_knumber const & arg2) const = 0; + _knumber * divide(_knumber const & arg2) const; + + virtual _knumber * power(_knumber const & exponent) const = 0; + + virtual int compare(_knumber const &arg2) const = 0; + + virtual operator signed long int (void) const = 0; + virtual operator unsigned long int (void) const = 0; + virtual operator double (void) const = 0; +}; + + + +class _knumerror : public _knumber +{ + public: + _knumerror(ErrorType error = UndefinedNumber) + : _error(error) { } + + _knumerror(_knumber const & num); + + _knumerror(const QString & num); + + //virtual ~_knumerror() { } + + _knumerror const & operator = (_knumerror const & num); + + virtual void copy(_knumber const & num) + { + _error = dynamic_cast<_knumerror const &>(num)._error; + } + + virtual NumType type(void) const {return SpecialType;} + + virtual QString const ascii(int prec = -1) const; + + virtual _knumber * abs(void) const; + virtual _knumber * intPart(void) const; + virtual int sign(void) const; + virtual _knumber * cbrt(void) const; + virtual _knumber * sqrt(void) const; + virtual _knumber * change_sign(void) const; + virtual _knumber * reciprocal(void) const; + virtual _knumber * add(_knumber const & arg2) const; + virtual _knumber * multiply(_knumber const & arg2) const; + + virtual _knumber * power(_knumber const & exponent) const; + + virtual int compare(_knumber const &arg2) const; + + virtual operator signed long int (void) const; + virtual operator unsigned long int (void) const; + virtual operator double (void) const; + + private: + + ErrorType _error; + + friend class _knuminteger; + friend class _knumfraction; + friend class _knumfloat; +}; + + + +class _knuminteger : public _knumber +{ + public: + _knuminteger(signed int num = 0) + { + mpz_init_set_si(_mpz, num); + } + + _knuminteger(unsigned int num) + { + mpz_init_set_ui(_mpz, num); + } + + _knuminteger(signed long int num) + { + mpz_init_set_si(_mpz, num); + } + + _knuminteger(unsigned long int num) + { + mpz_init_set_ui(_mpz, num); + } + + _knuminteger(unsigned long long int num); + + _knuminteger(_knumber const & num); + + _knuminteger(const QString & num); + + virtual ~_knuminteger() + { + mpz_clear(_mpz); + } + + _knuminteger const & operator = (_knuminteger const & num); + + virtual void copy(_knumber const & num) + { + mpz_set(_mpz, dynamic_cast<_knuminteger const &>(num)._mpz); + } + + virtual NumType type(void) const {return IntegerType;} + + virtual QString const ascii(int prec = -1) const; + + virtual _knumber * abs(void) const; + virtual _knumber * intPart(void) const; + virtual int sign(void) const; + virtual _knumber * cbrt(void) const; + virtual _knumber * sqrt(void) const; + virtual _knumber * change_sign(void) const; + virtual _knumber * reciprocal(void) const; + virtual _knumber * add(_knumber const & arg2) const; + virtual _knumber * multiply(_knumber const & arg2) const; + + virtual int compare(_knumber const &arg2) const; + + virtual _knumber * power(_knumber const & exponent) const; + + virtual operator signed long int (void) const; + virtual operator unsigned long int (void) const; + virtual operator double (void) const; + + _knuminteger * intAnd(_knuminteger const &arg2) const; + _knuminteger * intOr(_knuminteger const &arg2) const; + _knumber * mod(_knuminteger const &arg2) const; + _knumber * shift(_knuminteger const &arg2) const; + + private: + mpz_t _mpz; + + friend class _knumfraction; + friend class _knumfloat; +}; + + + +class _knumfraction : public _knumber +{ + public: + + _knumfraction(signed long int nom = 0, signed long int denom = 1) + { + mpq_init(_mpq); + mpq_set_si(_mpq, nom, denom); + mpq_canonicalize(_mpq); + } + + _knumfraction(_knumber const & num); + + _knumfraction(QString const & num); + + virtual ~_knumfraction() + { + mpq_clear(_mpq); + } + + virtual void copy(_knumber const & num) + { + mpq_set(_mpq, dynamic_cast<_knumfraction const &>(num)._mpq); + } + + virtual NumType type(void) const {return FractionType;} + + virtual QString const ascii(int prec = -1) const; + + bool isInteger(void) const; + + virtual _knumber * abs(void) const; + virtual _knumber * intPart(void) const; + virtual int sign(void) const; + virtual _knumber * cbrt(void) const; + virtual _knumber * sqrt(void) const; + virtual _knumber * change_sign(void) const; + virtual _knumber * reciprocal(void) const; + virtual _knumber * add(_knumber const & arg2) const; + virtual _knumber * multiply(_knumber const & arg2) const; + + virtual _knumber * power(_knumber const & exponent) const; + + virtual int compare(_knumber const &arg2) const; + + virtual operator signed long int (void) const; + virtual operator unsigned long int (void) const; + virtual operator double (void) const; + + private: + mpq_t _mpq; + + friend class _knuminteger; + friend class _knumfloat; +}; + +class _knumfloat : public _knumber +{ + public: + _knumfloat(double num = 1.0) + { + mpf_init(_mpf); + mpf_set_d(_mpf, num); + } + + _knumfloat(_knumber const & num); + + _knumfloat(QString const & num); + + virtual ~_knumfloat() + { + mpf_clear(_mpf); + } + + virtual void copy(_knumber const & num) + { + mpf_set(_mpf, dynamic_cast<_knumfloat const &>(num)._mpf); + } + + virtual NumType type(void) const {return FloatType;} + + virtual QString const ascii(int prec = -1) const; + + virtual _knumber * abs(void) const; + virtual _knumber * intPart(void) const; + virtual int sign(void) const; + virtual _knumber * cbrt(void) const; + virtual _knumber * sqrt(void) const; + virtual _knumber * change_sign(void) const; + virtual _knumber * reciprocal(void) const; + virtual _knumber * add(_knumber const & arg2) const; + virtual _knumber * multiply(_knumber const & arg2) const; + virtual _knumber * divide(_knumber const & arg2) const; + + virtual _knumber * power(_knumber const & exponent) const; + + virtual int compare(_knumber const &arg2) const; + + virtual operator signed long int (void) const; + virtual operator unsigned long int (void) const; + virtual operator double (void) const; + + private: + mpf_t _mpf; + + friend class _knuminteger; + friend class _knumfraction; +}; + + +#endif // _KNUMBER_PRIV_H diff --git a/kcalc/knumber/tests/Makefile.am b/kcalc/knumber/tests/Makefile.am new file mode 100644 index 0000000..73b0600 --- /dev/null +++ b/kcalc/knumber/tests/Makefile.am @@ -0,0 +1,32 @@ +# This file is part of the KDE libraries +# Copyright (C) 1996-1997 Matthias Kalle Dalheimer (kalle@kde.org) +# (C) 1997-1998 Stephan Kulow (coolo@kde.org) + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. + +# This library 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 +# Library General Public License for more details. + +# You should have received a copy of the GNU Library General Public License +# along with this library; see the file COPYING.LIB. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. + +INCLUDES = -I$(top_srcdir)/kcalc/knumber $(all_includes) + +check_PROGRAMS = knumbertest + +TESTS = knumbertest + +noinst_HEADERS = knumbertest.h + +METASOURCES = AUTO + +knumbertest_SOURCES = knumbertest.cpp +knumbertest_LDADD = ../libknumber.la $(LIB_QT) $(LIBGMP) +knumbertest_LDFLAGS = $(all_libraries) $(KDE_RPATH) diff --git a/kcalc/knumber/tests/knumbertest.cpp b/kcalc/knumber/tests/knumbertest.cpp new file mode 100644 index 0000000..814410e --- /dev/null +++ b/kcalc/knumber/tests/knumbertest.cpp @@ -0,0 +1,582 @@ +// +// Author: Klaus Niederkrueger <kniederk@math.uni-koeln.de> +// + +#include <stdlib.h> +#include <stdio.h> + +#include <iostream> +#include <qstring.h> + +#include "knumbertest.h" + +QString const numtypeToString(KNumber::NumType arg) +{ + switch(arg) { + case KNumber::SpecialType: + return QString("Special"); + case KNumber::IntegerType: + return QString("Integer"); + case KNumber::FractionType: + return QString("Fraction"); + case KNumber::FloatType: + return QString("Float"); + default: + return QString("Unknown:") + QString::number(static_cast<int>(arg)); + + } +} + +void checkResult(QString const &string, KNumber const & result, + QString const & desired_string, KNumber::NumType desired) +{ + std::cout << "Testing result of: " << string.ascii() << + " should give " << desired_string.ascii() << " and gives " << + result.toQString(8).ascii() << "....\n"; + std::cout << "The type of the result should be " << + numtypeToString(desired).ascii() << " and gives " << + numtypeToString(result.type()).ascii() << ".... "; + + if (result.type() == desired && + result.toQString(8) == desired_string) { + std::cout << "OK\n"; + return; + } + + std::cout << "Failed\n"; + exit(1); +} + +void checkTruth(QString const &string, bool computation, + bool desired_result) +{ + std::cout << "Testing truth of: " << string.ascii() << + " should be " << desired_result << " and is " << + computation << "....\n"; + + if (computation == desired_result) { + std::cout << "OK\n"; + return; + } + + std::cout << "Failed\n"; + exit(1); +} + + +void checkType(QString const &string, KNumber::NumType test_arg, + KNumber::NumType desired) +{ + std::cout << "Testing type of: " << string.ascii() << " should give " << + numtypeToString(desired).ascii() << " and gives " << + numtypeToString(test_arg).ascii() << "...."; + + if (test_arg == desired) { + std::cout << "OK\n"; + return; + } + + std::cout << "Failed\n"; + exit(1); + +} + + +void testingCompare(void) +{ + std::cout << "\n\nTesting Compare:\n"; + + checkTruth("KNumber(5) == KNumber(2)", KNumber(5) == KNumber(2), false); + checkTruth("KNumber(5) > KNumber(2)", KNumber(5) > KNumber(2), true); + checkTruth("KNumber(5) < KNumber(2)", KNumber(5) < KNumber(2), false); + checkTruth("KNumber(5) < KNumber(0)", KNumber(5) < KNumber(0), false); + checkTruth("KNumber(-5) < KNumber(0)", KNumber(-5) < KNumber(0), true); + checkTruth("KNumber(5) >= KNumber(2)", KNumber(5) >= KNumber(2), true); + checkTruth("KNumber(5) <= KNumber(2)", KNumber(5) <= KNumber(2), false); + checkTruth("KNumber(5) != KNumber(2)", KNumber(5) != KNumber(2), true); + + checkTruth("KNumber(2) == KNumber(2)", KNumber(2) == KNumber(2), true); + checkTruth("KNumber(2) > KNumber(2)", KNumber(2) > KNumber(2), false); + checkTruth("KNumber(2) < KNumber(2)", KNumber(2) < KNumber(2), false); + checkTruth("KNumber(2) >= KNumber(2)", KNumber(2) >= KNumber(2), true); + checkTruth("KNumber(2) <= KNumber(2)", KNumber(2) <= KNumber(2), true); + checkTruth("KNumber(2) != KNumber(2)", KNumber(2) != KNumber(2), false); + + checkTruth("KNumber(5) == KNumber(\"1/2\")", KNumber(5) == KNumber("1/2"), false); + checkTruth("KNumber(5) > KNumber(\"1/2\")", KNumber(5) > KNumber("1/2"), true); + checkTruth("KNumber(5) < KNumber(\"1/2\")", KNumber(5) < KNumber("1/2"), false); + checkTruth("KNumber(5) >= KNumber(\"1/2\")", KNumber(5) >= KNumber("1/2"), true); + checkTruth("KNumber(5) <= KNumber(\"1/2\")", KNumber(5) <= KNumber("1/2"), false); + checkTruth("KNumber(5) != KNumber(\"1/2\")", KNumber(5) != KNumber("1/2"), true); + + checkTruth("KNumber(\"1/2\") == KNumber(\"1/2\")", KNumber("1/2") == KNumber("1/2"), true); + checkTruth("KNumber(\"1/2\") > KNumber(\"1/2\")", KNumber("1/2") > KNumber("1/2"), false); + checkTruth("KNumber(\"1/2\") < KNumber(\"1/2\")", KNumber("1/2") < KNumber("1/2"), false); + checkTruth("KNumber(\"1/2\") >= KNumber(\"1/2\")", KNumber("1/2") >= KNumber("1/2"), true); + checkTruth("KNumber(\"1/2\") <= KNumber(\"1/2\")", KNumber("1/2") <= KNumber("1/2"), true); + checkTruth("KNumber(\"1/2\") != KNumber(\"1/2\")", KNumber("1/2") != KNumber("1/2"), false); + + checkTruth("KNumber(\"3/2\") == KNumber(\"1/2\")", KNumber("3/2") == KNumber("1/2"), false); + checkTruth("KNumber(\"3/2\") > KNumber(\"1/2\")", KNumber("3/2") > KNumber("1/2"), true); + checkTruth("KNumber(\"3/2\") < KNumber(\"1/2\")", KNumber("3/2") < KNumber("1/2"), false); + checkTruth("KNumber(\"3/2\") >= KNumber(\"1/2\")", KNumber("3/2") >= KNumber("1/2"), true); + checkTruth("KNumber(\"3/2\") <= KNumber(\"1/2\")", KNumber("3/2") <= KNumber("1/2"), false); + checkTruth("KNumber(\"3/2\") != KNumber(\"1/2\")", KNumber("3/2") != KNumber("1/2"), true); + +} + + +void testingAdditions(void) +{ + std::cout << "\n\nTesting additions:\n"; + + checkResult("KNumber(5) + KNumber(2)", KNumber(5) + KNumber(2), "7", KNumber::IntegerType); + checkResult("KNumber(5) + KNumber(\"2/3\")", KNumber(5) + KNumber("2/3"), "17/3", KNumber::FractionType); + checkResult("KNumber(5) + KNumber(\"2.3\")", KNumber(5) + KNumber("2.3"), "7.3", KNumber::FloatType); + + checkResult("KNumber(\"5/3\") + KNumber(2)", KNumber("5/3") + KNumber(2), "11/3", KNumber::FractionType); + checkResult("KNumber(\"5/3\") + KNumber(\"2/3\")", KNumber("5/3") + KNumber("2/3"), "7/3", KNumber::FractionType); + checkResult("KNumber(\"5/3\") + KNumber(\"1/3\")", KNumber("5/3") + KNumber("1/3"), "2", KNumber::IntegerType); + checkResult("KNumber(\"5/3\") + KNumber(\"-26/3\")", KNumber("5/3") + KNumber("-26/3"), "-7", KNumber::IntegerType); + checkResult("KNumber(\"5/2\") + KNumber(2.3)", KNumber("5/2") + KNumber(2.3), "4.8", KNumber::FloatType); + + checkResult("KNumber(5.3) + KNumber(2)", KNumber(5.3) + KNumber(2), "7.3", KNumber::FloatType); + checkResult("KNumber(5.3) + KNumber(\"2/4\")", KNumber(5.3) + KNumber("2/4"), "5.8", KNumber::FloatType); + checkResult("KNumber(5.3) + KNumber(2.3)", KNumber(5.3) + KNumber(2.3), "7.6", KNumber::FloatType); + +} + +void testingSubtractions(void) +{ + std::cout << "\n\nTesting subtractions:\n"; + + checkResult("KNumber(5) - KNumber(2)", KNumber(5) - KNumber(2), "3", KNumber::IntegerType); + checkResult("KNumber(5) - KNumber(\"2/3\")", KNumber(5) - KNumber("2/3"), "13/3", KNumber::FractionType); + checkResult("KNumber(5) - KNumber(2.3)", KNumber(5) - KNumber(2.3), "2.7", KNumber::FloatType); + + checkResult("KNumber(\"5/3\") - KNumber(2)", KNumber("5/3") - KNumber(2), "-1/3", KNumber::FractionType); + checkResult("KNumber(\"5/3\") - KNumber(\"1/3\")", KNumber("5/3") - KNumber("1/3"), "4/3", KNumber::FractionType); + checkResult("KNumber(\"5/3\") - KNumber(\"2/3\")", KNumber("5/3") - KNumber("2/3"), "1", KNumber::IntegerType); + checkResult("KNumber(\"-5/3\") - KNumber(\"4/3\")", KNumber("-5/3") - KNumber("4/3"), "-3", KNumber::IntegerType); + checkResult("KNumber(\"5/4\") - KNumber(2.2)", KNumber("5/4") - KNumber(2.2), "-0.95", KNumber::FloatType); + + checkResult("KNumber(5.3) - KNumber(2)", KNumber(5.3) - KNumber(2), "3.3", KNumber::FloatType); + checkResult("KNumber(5.3) - KNumber(\"3/4\")", KNumber(5.3) - KNumber("3/4"), "4.55", KNumber::FloatType); + checkResult("KNumber(5.3) - KNumber(2.3)", KNumber(5.3) - KNumber(2.3), "3", KNumber::FloatType); + +} + + +void testingMultiplications(void) +{ + std::cout << "\n\nTesting multiplications:\n"; + + checkResult("KNumber(5) * KNumber(2)", KNumber(5) * KNumber(2), "10", KNumber::IntegerType); + checkResult("KNumber(5) * KNumber(\"2/3\")", KNumber(5) * KNumber("2/3"), "10/3", KNumber::FractionType); + checkResult("KNumber(5) * KNumber(\"2/5\")", KNumber(5) * KNumber("2/5"), "2", KNumber::IntegerType); + checkResult("KNumber(5) * KNumber(2.3)", KNumber(5) * KNumber(2.3), "11.5", KNumber::FloatType); + checkResult("KNumber(0) * KNumber(\"2/5\")", KNumber(0) * KNumber("2/5"), "0", KNumber::IntegerType); + checkResult("KNumber(0) * KNumber(2.3)", KNumber(0) * KNumber(2.3), "0", KNumber::IntegerType); + + checkResult("KNumber(\"5/3\") * KNumber(2)", KNumber("5/3") * KNumber(2), "10/3", KNumber::FractionType); + checkResult("KNumber(\"5/3\") * KNumber(0)", KNumber("5/3") * KNumber(0), "0", KNumber::IntegerType); + checkResult("KNumber(\"5/3\") * KNumber(\"2/3\")", KNumber("5/3") * KNumber("2/3"), "10/9", KNumber::FractionType); + checkResult("KNumber(\"25/6\") * KNumber(\"12/5\")", KNumber("25/6") * KNumber("12/5"), "10", KNumber::IntegerType); + checkResult("KNumber(\"5/2\") * KNumber(2.3)", KNumber("5/2") * KNumber(2.3), "5.75",KNumber::FloatType); + + checkResult("KNumber(5.3) * KNumber(2)", KNumber(5.3) * KNumber(2), "10.6", KNumber::FloatType); + checkResult("KNumber(5.3) * KNumber(0)", KNumber(5.3) * KNumber(0), "0", KNumber::IntegerType); + checkResult("KNumber(5.3) * KNumber(\"1/2\")", KNumber(5.3) * KNumber("1/2"), "2.65", KNumber::FloatType); + checkResult("KNumber(5.3) * KNumber(2.3)", KNumber(5.3) * KNumber(2.3), "12.19", KNumber::FloatType); + +} + +void testingDivisions(void) +{ + std::cout << "\n\nTesting divisions:\n"; + + checkResult("KNumber(5) / KNumber(2)", KNumber(5) / KNumber(2), "5/2", KNumber::FractionType); + checkResult("KNumber(122) / KNumber(2)", KNumber(122) / KNumber(2), "61", KNumber::IntegerType); + checkResult("KNumber(12) / KNumber(0)", KNumber(12) / KNumber(0), "inf", KNumber::SpecialType); + checkResult("KNumber(-12) / KNumber(0)", KNumber(-12) / KNumber(0), "-inf", KNumber::SpecialType); + checkResult("KNumber(5) / KNumber(\"2/3\")", KNumber(5) / KNumber("2/3"), "15/2", KNumber::FractionType); + checkResult("KNumber(6) / KNumber(\"2/3\")", KNumber(6) / KNumber("2/3"), "9", KNumber::IntegerType); + checkResult("KNumber(5) / KNumber(2.5)", KNumber(5) / KNumber(2.5), "2", KNumber::FloatType); + checkResult("KNumber(5) / KNumber(0.0)", KNumber(5) / KNumber(0.0), "inf", KNumber::SpecialType); + checkResult("KNumber(-5) / KNumber(0.0)", KNumber(-5) / KNumber(0.0), "-inf", KNumber::SpecialType); + + checkResult("KNumber(\"5/3\") / KNumber(2)", KNumber("5/3") / KNumber(2), "5/6", KNumber::FractionType); + checkResult("KNumber(\"5/3\") / KNumber(0)", KNumber("5/3") / KNumber(0), "inf", KNumber::SpecialType); + checkResult("KNumber(\"-5/3\") / KNumber(0)", KNumber("-5/3") / KNumber(0), "-inf", KNumber::SpecialType); + checkResult("KNumber(\"5/3\") / KNumber(\"2/3\")", KNumber("5/3") / KNumber("2/3"), "5/2", KNumber::FractionType); + checkResult("KNumber(\"49/3\") / KNumber(\"7/9\")", KNumber("49/3") / KNumber("7/9"), "21", KNumber::IntegerType); + checkResult("KNumber(\"5/2\") / KNumber(2.5)", KNumber("5/2") / KNumber(2.5), "1", KNumber::FloatType); + checkResult("KNumber(\"5/2\") / KNumber(0.0)", KNumber("5/2") / KNumber(0.0), "inf", KNumber::SpecialType); + checkResult("KNumber(\"-5/2\") / KNumber(0.0)", KNumber("-5/2") / KNumber(0.0), "-inf", KNumber::SpecialType); + + checkResult("KNumber(5.3) / KNumber(2)", KNumber(5.3) / KNumber(2), "2.65", KNumber::FloatType); + checkResult("KNumber(5.3) / KNumber(0)", KNumber(5.3) / KNumber(0), "inf", KNumber::SpecialType); + checkResult("KNumber(-5.3) / KNumber(0)", KNumber(-5.3) / KNumber(0), "-inf", KNumber::SpecialType); + checkResult("KNumber(5.3) / KNumber(\"2/3\")", KNumber(5.3) / KNumber("2/3"), "7.95", KNumber::FloatType); + checkResult("KNumber(5.5) / KNumber(2.5)", KNumber(5.5) / KNumber(2.5), "2.2", KNumber::FloatType); + checkResult("KNumber(5.5) / KNumber(0.0)", KNumber(5.5) / KNumber(0.0), "inf", KNumber::SpecialType); + checkResult("KNumber(-5.5) / KNumber(0.0)", KNumber(-5.5) / KNumber(0.0), "-inf", KNumber::SpecialType); +} + +void testingModulus(void) +{ + std::cout << "\n\nTesting modulus:\n"; + + checkResult("KNumber(23) % KNumber(4)", KNumber(23) % KNumber(4), "3", KNumber::IntegerType); + checkResult("KNumber(12) % KNumber(-5)", KNumber(12) % KNumber(-5), "2", KNumber::IntegerType); + checkResult("KNumber(-12) % KNumber(5)", KNumber(-12) % KNumber(5), "3", KNumber::IntegerType); + checkResult("KNumber(12) % KNumber(0)", KNumber(-12) % KNumber(0), "nan", KNumber::SpecialType); + checkResult("KNumber(-12) % KNumber(0)", KNumber(-12) % KNumber(0), "nan", KNumber::SpecialType); + +#warning test for other types + +} + +void testingAndOr(void) +{ + std::cout << "\n\nTesting And/Or:\n"; + + checkResult("KNumber(17) & KNumber(9)", KNumber(17) & KNumber(9), "1", KNumber::IntegerType); + checkResult("KNumber(17) | KNumber(9)", KNumber(17) | KNumber(9), "25", KNumber::IntegerType); + checkResult("KNumber(1023) & KNumber(255)", KNumber(1023) & KNumber(255), "255", KNumber::IntegerType); + checkResult("KNumber(1023) | KNumber(255)", KNumber(1023) | KNumber(255), "1023", KNumber::IntegerType); + +#warning test for other types + +} + + +void testingAbs(void) +{ + std::cout << "\n\nTesting absolute value:\n"; + + checkResult("KNumber(5).abs()", KNumber(5).abs(), "5", KNumber::IntegerType); + checkResult("KNumber(\"2/3\").abs()", KNumber("2/3").abs(), "2/3", KNumber::FractionType); + checkResult("KNumber(\"2.3\").abs()", KNumber("2.3").abs(), "2.3", KNumber::FloatType); + + checkResult("KNumber(-5).abs()", KNumber(-5).abs(), "5", KNumber::IntegerType); + checkResult("KNumber(\"-2/3\").abs()", KNumber("-2/3").abs(), "2/3", KNumber::FractionType); + checkResult("KNumber(\"-2.3\").abs()", KNumber("-2.3").abs(), "2.3", KNumber::FloatType); +} + +void testingTruncateToInteger(void) +{ + std::cout << "\n\nTesting truncate to an integer:\n"; + + checkResult("KNumber(16).integerPart()", KNumber(16).integerPart(), "16", KNumber::IntegerType); + checkResult("KNumber(\"43/9\").integerPart()", KNumber("43/9").integerPart(), "4", KNumber::IntegerType); + checkResult("KNumber(\"-43/9\").integerPart()", KNumber("-43/9").integerPart(), "-4", KNumber::IntegerType); + checkResult("KNumber(\"5.25\").integerPart()", KNumber("5.25").integerPart(), "5", KNumber::IntegerType); + checkResult("KNumber(\"-5.25\").integerPart()", KNumber("-5.25").integerPart(), "-5", KNumber::IntegerType); +} + + +void testingSqrt(void) +{ + std::cout << "\n\nTesting square root, cubic root:\n"; + + checkResult("KNumber(16).sqrt()", KNumber(16).sqrt(), "4", KNumber::IntegerType); + checkResult("KNumber(-16).sqrt()", KNumber(-16).sqrt(), "nan", KNumber::SpecialType); + checkResult("KNumber(\"16/9\").sqrt()", KNumber("16/9").sqrt(), "4/3", KNumber::FractionType); + checkResult("KNumber(\"-16/9\").sqrt()", KNumber("-16/9").sqrt(), "nan", KNumber::SpecialType); + checkResult("KNumber(2).sqrt()", KNumber(2).sqrt(), "1.4142136", KNumber::FloatType); + checkResult("KNumber(\"2/3\").sqrt()", KNumber("2/3").sqrt(), "0.81649658", KNumber::FloatType); + checkResult("KNumber(\"0.25\").sqrt()", KNumber("0.25").sqrt(), "0.5", KNumber::FloatType); + checkResult("KNumber(\"-0.25\").sqrt()", KNumber("-0.25").sqrt(), "nan", KNumber::SpecialType); + + + checkResult("KNumber(27).cbrt()", KNumber(27).cbrt(), "3", KNumber::IntegerType); + checkResult("KNumber(-27).cbrt()", KNumber(-27).cbrt(), "-3", KNumber::IntegerType); + checkResult("KNumber(\"27/8\").cbrt()", KNumber("27/8").cbrt(), "3/2", KNumber::FractionType); + checkResult("KNumber(\"-8/27\").cbrt()", KNumber("-8/27").cbrt(), "-2/3", KNumber::FractionType); +#warning need to check non-perfect cube roots + // checkResult("KNumber(2).cbrt()", KNumber(2).cbrt(), "1.4142136", KNumber::FloatType); + // checkResult("KNumber(\"2/3\").cbrt()", KNumber("2/3").cbrt(), "0.81649658", KNumber::FloatType); + // checkResult("KNumber(\"0.25\").cbrt()", KNumber("0.25").cbrt(), "0.5", KNumber::FloatType); + // checkResult("KNumber(\"-0.25\").cbrt()", KNumber("-0.25").cbrt(), "nan", KNumber::SpecialType); + +} + +void testingShifts(void) +{ + std::cout << "\n\nTesting left/right shift:\n"; + + checkResult("KNumber(16) << KNumber(2)", KNumber(16) << KNumber(2), "64", KNumber::IntegerType); + checkResult("KNumber(16) >> KNumber(2)", KNumber(16) >> KNumber(2), "4", KNumber::IntegerType); + +} + +void testingPower(void) +{ + std::cout << "\n\nTesting Power:\n"; + + checkResult("KNumber(0) ^ KNumber(-4)", KNumber(0).power(KNumber(-4)), "inf", KNumber::SpecialType); + checkResult("KNumber(5) ^ KNumber(4)", KNumber(5).power(KNumber(4)), "625", KNumber::IntegerType); + checkResult("KNumber(122) ^ KNumber(0)", KNumber(122).power(KNumber(0)), "1", KNumber::IntegerType); + checkResult("KNumber(-5) ^ KNumber(0)", KNumber(-5).power(KNumber(0)), "nan", KNumber::SpecialType); + checkResult("KNumber(-2) ^ KNumber(3)", KNumber(-2).power(KNumber(3)), "-8", KNumber::IntegerType); + checkResult("KNumber(-2) ^ KNumber(4)", KNumber(-2).power(KNumber(4)), "16", KNumber::IntegerType); + checkResult("KNumber(5) ^ KNumber(-2)", KNumber(5).power(KNumber(-2)), "1/25", KNumber::FractionType); + checkResult("KNumber(8) ^ KNumber(\"2/3\")", KNumber(8).power(KNumber("2/3")), "4", KNumber::IntegerType); + checkResult("KNumber(8) ^ KNumber(\"-2/3\")", KNumber(8).power(KNumber("-2/3")), "1/4", KNumber::FractionType); + checkResult("KNumber(-16) ^ KNumber(\"1/4\")", KNumber(-16).power(KNumber("1/4")), "nan", KNumber::SpecialType); + checkResult("KNumber(-8) ^ KNumber(\"1/3\")", KNumber(-8).power(KNumber("1/3")), "nan", KNumber::SpecialType); + checkResult("KNumber(5) ^ KNumber(0.0)", KNumber(5).power(KNumber(0.0)), "1", KNumber::IntegerType); + checkResult("KNumber(-5) ^ KNumber(0.0)", KNumber(-5).power(KNumber(0.0)), "nan", KNumber::SpecialType); + + checkResult("KNumber(\"5/3\") ^ KNumber(2)", KNumber("5/3").power(KNumber(2)), "25/9", KNumber::FractionType); + checkResult("KNumber(\"5/3\") ^ KNumber(0)", KNumber("5/3").power(KNumber(0)), "1", KNumber::IntegerType); + checkResult("KNumber(\"-5/3\") ^ KNumber(0)", KNumber("-5/3").power(KNumber(0)), "nan", KNumber::SpecialType); + checkResult("KNumber(\"8/27\") ^ KNumber(\"2/3\")", KNumber("8/27").power(KNumber("2/3")), "4/9", KNumber::FractionType); + checkResult("KNumber(\"49/3\") ^ KNumber(\"7/9\")", KNumber("49/3").power(KNumber("7/9")), "21", KNumber::IntegerType); + checkResult("KNumber(\"5/2\") ^ KNumber(2.5)", KNumber("5/2").power(KNumber(2.5)), "1", KNumber::FloatType); + checkResult("KNumber(\"5/2\") ^ KNumber(0.0)", KNumber("5/2").power(KNumber(0.0)), "inf", KNumber::SpecialType); + checkResult("KNumber(\"-5/2\") ^ KNumber(0.0)", KNumber("-5/2").power(KNumber(0.0)), "-inf", KNumber::SpecialType); + + checkResult("KNumber(5.3) ^ KNumber(2)", KNumber(5.3).power(KNumber(2)), "2.65", KNumber::FloatType); + checkResult("KNumber(5.3) ^ KNumber(0)", KNumber(5.3).power(KNumber(0)), "inf", KNumber::SpecialType); + checkResult("KNumber(-5.3) ^ KNumber(0)", KNumber(-5.3).power(KNumber(0)), "-inf", KNumber::SpecialType); + checkResult("KNumber(5.3) ^ KNumber(\"2/3\")", KNumber(5.3).power(KNumber("2/3")), "7.95", KNumber::FloatType); + checkResult("KNumber(5.5) ^ KNumber(2.5)", KNumber(5.5).power(KNumber(2.5)), "2.2", KNumber::FloatType); + checkResult("KNumber(5.5) ^ KNumber(0.0)", KNumber(5.5).power(KNumber(0.0)), "inf", KNumber::SpecialType); + checkResult("KNumber(-5.5) ^ KNumber(0.0)", KNumber(-5.5).power(KNumber(0.0)), "-inf", KNumber::SpecialType); +} + +void testingInfArithmetic(void) +{ + std::cout << "\n\nTesting inf/nan-arithmetics:\n"; + + KNumber tmp_inf = KNumber("inf"); + KNumber tmp_mininf = KNumber("-inf"); + KNumber tmp_nan = KNumber("nan"); + + checkResult("inf + KNumber(2)", tmp_inf + KNumber(2), "inf", KNumber::SpecialType); + checkResult("KNumber(-5) + inf", KNumber(-5) + tmp_inf, "inf", KNumber::SpecialType); + checkResult("inf + KNumber(\"1/2\")", tmp_inf + KNumber("1/2"), "inf", KNumber::SpecialType); + checkResult("KNumber(\"-5/3\") + inf", KNumber("-5/3") + tmp_inf, "inf", KNumber::SpecialType); + checkResult("inf + KNumber(2.01)", tmp_inf + KNumber(2.01), "inf", KNumber::SpecialType); + checkResult("KNumber(-5.4) + inf", KNumber(-5.4) + tmp_inf, "inf", KNumber::SpecialType); + checkResult("mininf + KNumber(2)", tmp_mininf + KNumber(2), "-inf", KNumber::SpecialType); + checkResult("KNumber(-5) + mininf", KNumber(-5) + tmp_mininf, "-inf", KNumber::SpecialType); + checkResult("mininf + KNumber(\"1/2\")", tmp_mininf + KNumber("1/2"), "-inf", KNumber::SpecialType); + checkResult("KNumber(\"-5/3\") + mininf", KNumber("-5/3") + tmp_mininf, "-inf", KNumber::SpecialType); + checkResult("mininf + KNumber(2.01)", tmp_mininf + KNumber(2.01), "-inf", KNumber::SpecialType); + checkResult("KNumber(-5.4) + mininf", KNumber(-5.4) + tmp_mininf, "-inf", KNumber::SpecialType); + checkResult("nan + KNumber(2)", tmp_nan + KNumber(2), "nan", KNumber::SpecialType); + checkResult("KNumber(-5) + nan", KNumber(-5) + tmp_nan, "nan", KNumber::SpecialType); + checkResult("nan + KNumber(\"1/2\")", tmp_nan + KNumber("1/2"), "nan", KNumber::SpecialType); + checkResult("KNumber(\"-5/3\") + nan", KNumber("-5/3") + tmp_nan, "nan", KNumber::SpecialType); + checkResult("nan + KNumber(2.01)", tmp_nan + KNumber(2.01), "nan", KNumber::SpecialType); + checkResult("KNumber(-5.4) + nan", KNumber(-5.4) + tmp_nan, "nan", KNumber::SpecialType); + checkResult("inf + inf", tmp_inf + tmp_inf, "inf", KNumber::SpecialType); + checkResult("inf + mininf", tmp_inf + tmp_mininf, "nan", KNumber::SpecialType); + checkResult("mininf + inf", tmp_mininf + tmp_inf, "nan", KNumber::SpecialType); + checkResult("mininf + mininf", tmp_mininf + tmp_mininf, "-inf", KNumber::SpecialType); + checkResult("inf + nan", tmp_inf + tmp_nan, "nan", KNumber::SpecialType); + checkResult("mininf + nan", tmp_mininf + tmp_nan, "nan", KNumber::SpecialType); + checkResult("nan + inf", tmp_nan + tmp_inf, "nan", KNumber::SpecialType); + checkResult("mininf + nan", tmp_mininf + tmp_nan, "nan", KNumber::SpecialType); + + + checkResult("inf - KNumber(2)", tmp_inf - KNumber(2), "inf", KNumber::SpecialType); + checkResult("KNumber(-5) - inf", KNumber(-5) - tmp_inf, "-inf", KNumber::SpecialType); + checkResult("inf - KNumber(\"1/2\")", tmp_inf - KNumber("1/2"), "inf", KNumber::SpecialType); + checkResult("KNumber(\"-5/3\") - inf", KNumber("-5/3") - tmp_inf, "-inf", KNumber::SpecialType); + checkResult("inf - KNumber(2.01)", tmp_inf - KNumber(2.01), "inf", KNumber::SpecialType); + checkResult("KNumber(-5.4) - inf", KNumber(-5.4) - tmp_inf, "-inf", KNumber::SpecialType); + checkResult("mininf - KNumber(2)", tmp_mininf - KNumber(2), "-inf", KNumber::SpecialType); + checkResult("KNumber(-5) - mininf", KNumber(-5) - tmp_mininf, "inf", KNumber::SpecialType); + checkResult("mininf - KNumber(\"1/2\")", tmp_mininf - KNumber("1/2"), "-inf", KNumber::SpecialType); + checkResult("KNumber(\"-5/3\") - mininf", KNumber("-5/3") - tmp_mininf, "inf", KNumber::SpecialType); + checkResult("mininf - KNumber(2.01)", tmp_mininf - KNumber(2.01), "-inf", KNumber::SpecialType); + checkResult("KNumber(-5.4) - mininf", KNumber(-5.4) - tmp_mininf, "inf", KNumber::SpecialType); + checkResult("nan - KNumber(2)", tmp_nan - KNumber(2), "nan", KNumber::SpecialType); + checkResult("KNumber(-5) - nan", KNumber(-5) - tmp_nan, "nan", KNumber::SpecialType); + checkResult("nan - KNumber(\"1/2\")", tmp_nan - KNumber("1/2"), "nan", KNumber::SpecialType); + checkResult("KNumber(\"-5/3\") - nan", KNumber("-5/3") - tmp_nan, "nan", KNumber::SpecialType); + checkResult("nan - KNumber(2.01)", tmp_nan - KNumber(2.01), "nan", KNumber::SpecialType); + checkResult("KNumber(-5.4) - nan", KNumber(-5.4) - tmp_nan, "nan", KNumber::SpecialType); + checkResult("inf - inf", tmp_inf - tmp_inf, "nan", KNumber::SpecialType); + checkResult("inf - mininf", tmp_inf - tmp_mininf, "inf", KNumber::SpecialType); + checkResult("mininf - inf", tmp_mininf - tmp_inf, "-inf", KNumber::SpecialType); + checkResult("mininf - mininf", tmp_mininf - tmp_mininf, "nan", KNumber::SpecialType); + checkResult("inf - nan", tmp_inf - tmp_nan, "nan", KNumber::SpecialType); + checkResult("mininf - nan", tmp_mininf - tmp_nan, "nan", KNumber::SpecialType); + checkResult("nan - inf", tmp_nan - tmp_inf, "nan", KNumber::SpecialType); + checkResult("mininf - nan", tmp_mininf - tmp_nan, "nan", KNumber::SpecialType); + + + checkResult("inf * KNumber(2)", tmp_inf * KNumber(2), "inf", KNumber::SpecialType); + checkResult("KNumber(-5) * inf", KNumber(-5) * tmp_inf, "-inf", KNumber::SpecialType); + checkResult("inf * KNumber(\"1/2\")", tmp_inf * KNumber("1/2"), "inf", KNumber::SpecialType); + checkResult("KNumber(\"-5/3\") * inf", KNumber("-5/3") * tmp_inf, "-inf", KNumber::SpecialType); + checkResult("inf * KNumber(2.01)", tmp_inf * KNumber(2.01), "inf", KNumber::SpecialType); + checkResult("KNumber(-5.4) * inf", KNumber(-5.4) * tmp_inf, "-inf", KNumber::SpecialType); + checkResult("mininf * KNumber(2)", tmp_mininf * KNumber(2), "-inf", KNumber::SpecialType); + checkResult("KNumber(-5) * mininf", KNumber(-5) * tmp_mininf, "inf", KNumber::SpecialType); + checkResult("mininf * KNumber(\"1/2\")", tmp_mininf * KNumber("1/2"), "-inf", KNumber::SpecialType); + checkResult("KNumber(\"-5/3\") * mininf", KNumber("-5/3") * tmp_mininf, "inf", KNumber::SpecialType); + checkResult("mininf * KNumber(2.01)", tmp_mininf * KNumber(2.01), "-inf", KNumber::SpecialType); + checkResult("KNumber(-5.4) * mininf", KNumber(-5.4) * tmp_mininf, "inf", KNumber::SpecialType); + checkResult("nan * KNumber(2)", tmp_nan * KNumber(2), "nan", KNumber::SpecialType); + checkResult("KNumber(-5) * nan", KNumber(-5) * tmp_nan, "nan", KNumber::SpecialType); + checkResult("nan * KNumber(\"1/2\")", tmp_nan * KNumber("1/2"), "nan", KNumber::SpecialType); + checkResult("KNumber(\"-5/3\") * nan", KNumber("-5/3") * tmp_nan, "nan", KNumber::SpecialType); + checkResult("nan * KNumber(2.01)", tmp_nan * KNumber(2.01), "nan", KNumber::SpecialType); + checkResult("KNumber(-5.4) * nan", KNumber(-5.4) * tmp_nan, "nan", KNumber::SpecialType); + checkResult("inf * inf", tmp_inf * tmp_inf, "inf", KNumber::SpecialType); + checkResult("inf * mininf", tmp_inf * tmp_mininf, "-inf", KNumber::SpecialType); + checkResult("mininf * inf", tmp_mininf * tmp_inf, "-inf", KNumber::SpecialType); + checkResult("mininf * mininf", tmp_mininf * tmp_mininf, "inf", KNumber::SpecialType); + checkResult("inf * nan", tmp_inf * tmp_nan, "nan", KNumber::SpecialType); + checkResult("mininf * nan", tmp_mininf * tmp_nan, "nan", KNumber::SpecialType); + checkResult("nan * inf", tmp_nan * tmp_inf, "nan", KNumber::SpecialType); + checkResult("mininf * nan", tmp_mininf * tmp_nan, "nan", KNumber::SpecialType); + checkResult("KNumber(0) * inf", KNumber(0) * tmp_inf, "nan", KNumber::SpecialType); + checkResult("KNumber(0) * mininf", KNumber(0) * tmp_mininf, "nan", KNumber::SpecialType); + checkResult("inf * KNumber(0)", tmp_inf * KNumber(0), "nan", KNumber::SpecialType); + checkResult("mininf * KNumber(0)", tmp_mininf * KNumber(0), "nan", KNumber::SpecialType); + checkResult("KNumber(0.0) * inf", KNumber(0.0) * tmp_inf, "nan", KNumber::SpecialType); + checkResult("KNumber(0.0) * mininf", KNumber(0.0) * tmp_mininf, "nan", KNumber::SpecialType); + checkResult("inf * KNumber(0.0)", tmp_inf * KNumber(0.0), "nan", KNumber::SpecialType); + checkResult("mininf * KNumber(0.0)", tmp_mininf * KNumber(0.0), "nan", KNumber::SpecialType); + + + checkResult("inf / KNumber(2)", tmp_inf / KNumber(2), "inf", KNumber::SpecialType); + checkResult("KNumber(-5) / inf", KNumber(-5) / tmp_inf, "0", KNumber::IntegerType); + checkResult("inf / KNumber(\"1/2\")", tmp_inf / KNumber("1/2"), "inf", KNumber::SpecialType); + checkResult("KNumber(\"-5/3\") / inf", KNumber("-5/3") / tmp_inf, "0", KNumber::IntegerType); + checkResult("inf / KNumber(2.01)", tmp_inf / KNumber(2.01), "inf", KNumber::SpecialType); + checkResult("KNumber(-5.4) / inf", KNumber(-5.4) / tmp_inf, "0", KNumber::IntegerType); + checkResult("mininf / KNumber(2)", tmp_mininf / KNumber(2), "-inf", KNumber::SpecialType); + checkResult("KNumber(-5) / mininf", KNumber(-5) / tmp_mininf, "0", KNumber::IntegerType); + checkResult("mininf / KNumber(\"1/2\")", tmp_mininf / KNumber("1/2"), "-inf", KNumber::SpecialType); + checkResult("KNumber(\"-5/3\") / mininf", KNumber("-5/3") / tmp_mininf, "0", KNumber::IntegerType); + checkResult("mininf / KNumber(2.01)", tmp_mininf / KNumber(2.01), "-inf", KNumber::SpecialType); + checkResult("KNumber(-5.4) / mininf", KNumber(-5.4) / tmp_mininf, "0", KNumber::IntegerType); + checkResult("nan / KNumber(2)", tmp_nan / KNumber(2), "nan", KNumber::SpecialType); + checkResult("KNumber(-5) / nan", KNumber(-5) / tmp_nan, "nan", KNumber::SpecialType); + checkResult("nan / KNumber(\"1/2\")", tmp_nan / KNumber("1/2"), "nan", KNumber::SpecialType); + checkResult("KNumber(\"-5/3\") / nan", KNumber("-5/3") / tmp_nan, "nan", KNumber::SpecialType); + checkResult("nan / KNumber(2.01)", tmp_nan / KNumber(2.01), "nan", KNumber::SpecialType); + checkResult("KNumber(-5.4) / nan", KNumber(-5.4) / tmp_nan, "nan", KNumber::SpecialType); + checkResult("inf / inf", tmp_inf / tmp_inf, "nan", KNumber::SpecialType); + checkResult("inf / mininf", tmp_inf / tmp_mininf, "nan", KNumber::SpecialType); + checkResult("mininf / inf", tmp_mininf / tmp_inf, "nan", KNumber::SpecialType); + checkResult("mininf / mininf", tmp_mininf / tmp_mininf, "nan", KNumber::SpecialType); + checkResult("inf / nan", tmp_inf / tmp_nan, "nan", KNumber::SpecialType); + checkResult("mininf / nan", tmp_mininf / tmp_nan, "nan", KNumber::SpecialType); + checkResult("nan / inf", tmp_nan / tmp_inf, "nan", KNumber::SpecialType); + checkResult("mininf / nan", tmp_mininf / tmp_nan, "nan", KNumber::SpecialType); + checkResult("KNumber(0) / inf", KNumber(0) / tmp_inf, "0", KNumber::IntegerType); + checkResult("KNumber(0) / mininf", KNumber(0) / tmp_mininf, "0", KNumber::IntegerType); + checkResult("inf / KNumber(0)", tmp_inf / KNumber(0), "inf", KNumber::SpecialType); + checkResult("mininf / KNumber(0)", tmp_mininf / KNumber(0), "-inf", KNumber::SpecialType); + checkResult("KNumber(0.0) / inf", KNumber(0.0) / tmp_inf, "0", KNumber::IntegerType); + checkResult("KNumber(0.0) / mininf", KNumber(0.0) / tmp_mininf, "0", KNumber::IntegerType); + checkResult("inf / KNumber(0.0)", tmp_inf / KNumber(0.0), "inf", KNumber::SpecialType); + checkResult("mininf / KNumber(0.0)", tmp_mininf / KNumber(0.0), "-inf", KNumber::SpecialType); +} + +void testingFloatPrecision(void) +{ + KNumber::setDefaultFloatPrecision(100); + checkResult("Precision >= 100: (KNumber(1) + KNumber(\"1e-80\")) - KNumber(1)", + (KNumber(1) + KNumber("1e-80")) - KNumber(1), "1e-80", KNumber::FloatType); + checkResult("Precision >= 100: (KNumber(1) + KNumber(\"1e-980\")) - KNumber(1)", + (KNumber(1) + KNumber("1e-980")) - KNumber(1), "0", KNumber::FloatType); + + KNumber::setDefaultFloatPrecision(1000); + checkResult("Precision >= 1000: (KNumber(1) + KNumber(\"1e-980\")) - KNumber(1)", + (KNumber(1) + KNumber("1e-980")) - KNumber(1), "1e-980", KNumber::FloatType); + +} + +void testingOutput(void) +{ + KNumber::setDefaultFloatOutput(false); + checkResult("Fractional output: KNumber(\"1/4\")", KNumber("1/4"), "1/4", KNumber::FractionType); + KNumber::setDefaultFloatOutput(true); + checkResult("Float: KNumber(\"1/4\")", KNumber("1/4"), "0.25", KNumber::FractionType); + KNumber::setDefaultFloatOutput(false); + KNumber::setSplitoffIntegerForFractionOutput(true); + checkResult("Fractional output: KNumber(\"1/4\")", KNumber("1/4"), "1/4", KNumber::FractionType); + checkResult("Fractional output: KNumber(\"-1/4\")", KNumber("-1/4"), "-1/4", KNumber::FractionType); + checkResult("Fractional output: KNumber(\"21/4\")", KNumber("21/4"), "5 1/4", KNumber::FractionType); + checkResult("Fractional output: KNumber(\"-21/4\")", KNumber("-21/4"), "-5 1/4", KNumber::FractionType); + KNumber::setSplitoffIntegerForFractionOutput(false); + checkResult("Fractional output: KNumber(\"1/4\")", KNumber("1/4"), "1/4", KNumber::FractionType); + checkResult("Fractional output: KNumber(\"-1/4\")", KNumber("-1/4"), "-1/4", KNumber::FractionType); + checkResult("Fractional output: KNumber(\"21/4\")", KNumber("21/4"), "21/4", KNumber::FractionType); + checkResult("Fractional output: KNumber(\"-21/4\")", KNumber("-21/4"), "-21/4", KNumber::FractionType); +} + + +int main(void) +{ + std::cout << "Testing Constructors:\n"; + + checkResult("KNumber(5)", KNumber(5), "5", KNumber::IntegerType); + checkType("KNumber(5.3)", KNumber(5.3).type(), KNumber::FloatType); + checkType("KNumber(0.0)", KNumber(0.0).type(), KNumber::FloatType); + + checkResult("KNumber(\"5\")", KNumber("5"), "5", KNumber::IntegerType); + checkResult("KNumber(\"5/3\")", KNumber("5/3"), "5/3", KNumber::FractionType); + checkResult("KNumber(\"5/1\")", KNumber("5/1"), "5", KNumber::IntegerType); + checkResult("KNumber(\"0/12\")", KNumber("0/12"), "0", KNumber::IntegerType); + KNumber::setDefaultFractionalInput(true); + std::cout << "Read decimals as fractions:\n"; + checkResult("KNumber(\"5\")", KNumber("5"), "5", KNumber::IntegerType); + checkResult("KNumber(\"1.2\")", KNumber("1.2"), "6/5", KNumber::FractionType); + checkResult("KNumber(\"-0.02\")", KNumber("-0.02"), "-1/50", KNumber::FractionType); + checkResult("KNumber(\"5e-2\")", KNumber("5e-2"), "1/20", KNumber::FractionType); + checkResult("KNumber(\"1.2e3\")", KNumber("1.2e3"), "1200", KNumber::IntegerType); + checkResult("KNumber(\"0.02e+1\")", KNumber("0.02e+1"), "1/5", KNumber::FractionType); + + KNumber::setDefaultFractionalInput(false); + std::cout << "Read decimals as floats:\n"; + checkResult("KNumber(\"5.3\")", KNumber("5.3"), "5.3", KNumber::FloatType); + + checkResult("KNumber(\"nan\")", KNumber("nan"), "nan", KNumber::SpecialType); + checkResult("KNumber(\"inf\")", KNumber("inf"), "inf", KNumber::SpecialType); + checkResult("KNumber(\"-inf\")", KNumber("-inf"), "-inf", KNumber::SpecialType); + + std::cout << "\n\nConstants:\n"; + + checkType("KNumber::Zero", KNumber::Zero.type(), KNumber::IntegerType); + checkType("KNumber::One", KNumber::One.type(), KNumber::IntegerType); + checkType("KNumber::MinusOne", KNumber::MinusOne.type(), KNumber::IntegerType); + checkType("KNumber::Pi", KNumber::Pi.type(), KNumber::FloatType); + + testingCompare(); + + testingAdditions(); + testingSubtractions(); + testingMultiplications(); + testingDivisions(); + + testingAndOr(); + testingModulus(); + + testingAbs(); + testingSqrt(); + //testingPower(); + testingTruncateToInteger(); + + testingShifts(); + + testingInfArithmetic(); + + testingFloatPrecision(); + + testingOutput(); + + return 0; +} + + diff --git a/kcalc/knumber/tests/knumbertest.h b/kcalc/knumber/tests/knumbertest.h new file mode 100644 index 0000000..b93dc4a --- /dev/null +++ b/kcalc/knumber/tests/knumbertest.h @@ -0,0 +1,9 @@ +#ifndef KNUMBERTEST_H +#define KNUMBERTEST_H + +#include "knumber.h" + +/** test: a small test program for KNumber + */ + +#endif // KNUMBERTEST_H diff --git a/kcalc/stats.cpp b/kcalc/stats.cpp new file mode 100644 index 0000000..909bed6 --- /dev/null +++ b/kcalc/stats.cpp @@ -0,0 +1,196 @@ +/* + $Id$ + + KCalc, a scientific calculator for the X window system using the + Qt widget libraries, available at no cost at http://www.troll.no + + Copyright (C) 1996 Bernd Johannes Wuebben + wuebben@math.cornell.edu + + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + + +#include "stats.h" +#ifdef DEBUG_STATS + #include <stdio.h> +#endif + +KStats::KStats() { + error_flag = false; +} + +KStats::~KStats() { +} + +void KStats::clearAll() { + mData.clear(); +} + +void KStats::enterData(KNumber const & _data) { + + mData.push_back(_data); +#ifdef DEBUG_STATS + printf("Added %Lg\n", _data); + printf("count %d\n", mData.size()); +#endif + +} + + +void KStats::clearLast(void) { + + mData.pop_back(); +#ifdef DEBUG_STATS + printf("count %d\n",mData.size()); +#endif + + +} + +KNumber KStats::sum(void) { + + KNumber result = 0; + QValueVector<KNumber>::iterator p; + + for(p = mData.begin(); p != mData.end(); ++p) { + result += *p; + } + +#ifdef DEBUG_STATS + printf("Sum %Lg\n", result); +#endif + + return result; +} + +KNumber KStats::median(void) { + + KNumber result = 0; + unsigned int bound; + size_t index; + + bound = count(); + + if (bound == 0){ + error_flag = true; + return 0; + } + + if (bound == 1) + return mData.at(0); + + // need to copy mData-list, because sorting afterwards + QValueVector<KNumber> tmp_mData(mData); + qHeapSort(tmp_mData); + + if( bound & 1) { // odd + index = (bound - 1 ) / 2 + 1; + result = tmp_mData.at(index - 1); + } else { // even + index = bound / 2; + result = ((tmp_mData.at(index - 1)) + (tmp_mData.at(index))) / KNumber(2); + } + + return result; +} + + +KNumber KStats::std_kernel(void) +{ + KNumber result = KNumber::Zero; + KNumber _mean; + QValueVector<KNumber>::iterator p; + + _mean = mean(); + + for(p = mData.begin(); p != mData.end(); ++p) { + result += (*p - _mean) * (*p - _mean); + } + + return result; +} + + +KNumber KStats::sum_of_squares() { + + KNumber result = 0; + QValueVector<KNumber>::iterator p; + + for(p = mData.begin(); p != mData.end(); ++p) { + result += ((*p) * (*p)); + } + + return result; +} + + +KNumber KStats::mean(void) +{ + if(count() == 0){ + error_flag = true; + return 0; + } + + return (sum() / KNumber(count())); +} + + +KNumber KStats::std(void) +{ + if(count() == 0){ + error_flag = true; + return KNumber::Zero; + } + + return (std_kernel() / KNumber(count())).sqrt(); +} + + +KNumber KStats::sample_std(void) { + KNumber result = 0; + + if(count() < 2 ){ + error_flag = true; + return KNumber::Zero; + } + + result = (std_kernel() / KNumber(count() - 1)).sqrt(); + + // result = result/(count() - 1); +#ifdef DEBUG_STATS + printf("sample std: %Lg\n",result); +#endif + + return result; +} + + +int KStats::count(void) const +{ + return static_cast<int>(mData.size()); +} + + +bool KStats::error() { + + bool value = error_flag; + error_flag = false; + return value; +} + + + diff --git a/kcalc/stats.h b/kcalc/stats.h new file mode 100644 index 0000000..48b7ddc --- /dev/null +++ b/kcalc/stats.h @@ -0,0 +1,60 @@ +/* + $Id$ + + KCalc, a scientific calculator for the X window system using the + Qt widget libraries, available at no cost at http://www.troll.no + + Copyright (C) 1996 Bernd Johannes Wuebben + wuebben@math.cornell.edu + + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef KSTATS_H +#define KSTATS_H + +#include <qvaluevector.h> +#include "knumber.h" + +class KStats { + +public: + KStats(); + ~KStats(); + +public: + void clearAll(); + void enterData(const KNumber & data); + void clearLast(); + KNumber sum(); + KNumber sum_of_squares(); + KNumber mean(); + KNumber median(); + KNumber std_kernel(); + KNumber std(); + KNumber sample_std(); + int count() const; + bool error(); + +private: + QValueVector<KNumber> mData; + bool error_flag; + +}; + + +#endif /*KSTATS_H*/ + diff --git a/kcalc/version.h b/kcalc/version.h new file mode 100644 index 0000000..9a591f3 --- /dev/null +++ b/kcalc/version.h @@ -0,0 +1 @@ +#define KCALCVERSION "2.0.6" |