Extcalc - Scientific Calculator

Version 0.9.0

Inhalt

1. Introduction

2. Source Files

3. Mathematical Classes

3.1 Important Basic Functions

3.2 Class Description

3.3 Usage of the Mathematical Classes

4. Internal Interfaces

4.1 Basic Structures

4.2 Variables

4.3 Config file and Preferences

5. Mathematical Algorithms

6. Installation Files




1. Introduction

This is the internal documentation of Calc and Extcalc. It is mainly for develops. Users don't need to read that.
It describes the source files and the internal structure of Calc and Extcalc and the Installer.
A description of the mathematical methods and algorithms is also be found here.



2. Source Files

File List:

All the files listed here, belong to the Extcalc program and they were coded by hand. The files, which were generated by QT, are not mentioned here.
Source Files:
extcalc.cpp
buttons.cpp
calcwidget.cpp
global.cpp
graph.cpp
graphout.cpp
graphpref.cpp
graphsolve.cpp
calctable.cpp
calcinput.cpp
calcpref.cpp
functiontable.cpp
table.cpp
tablepref.cpp
scriptedit.cpp
scriptpref.cpp
scriptio.cpp
matrixwidget.cpp
statistics.cpp
catalog.cpp
Header Files:
extcalc.h
buttons.h
calcwidget.h
global.h
graph.h
graphout.h
graphpref.h
graphsolve.h
calctable.h
calcinput.h
calcpref.h
functiontable.h
table.h
tablepref.h
scriptedit.h
scriptpref.h
matrixwidget.h
statistics.h
catalog.h
scriptio.h
Extra Header Files:
list.h
calclocale.h

Source Tree

Here you can see the debpendencies beteween all header files.
  

  
                                     calclocale.h            list.h
                                          |                 /  |  \________________________
          ________________________________|________________/   |                 _________ \ ________________ catalog.h
         /                             global.h       _________|________________/       calctable.h___________      \______________________________________________________________________
        /  _______________________________|__________/_________|_______________/_____________|________________\______\________________\________________\____________________\_______________\_____________________________________________________________
       /  /                    /                    /    \     |              /       \      |             \  |        \               \                \                    \               \               \            \              \               \
  calcinput.h              buttons.h               /       graphout.h        /         graphsolve.h   functiontable.h  |               |                |                    |               |               |            |              |                |
      \____              _____/   __\_____________/              \______    /   ______/                /            \  |               |                |                    |               |               |            |              |                |
           \            /        /   \_________________________________ \  |   /______________________/              \ |               |                |                    |               |               |            |              |                |
            calcwidget.h________/                                       graph.h                                     table.h       scriptedit.h       scriptio.h       matrixwidget.h    statistics.h   graphpref.h    calcpref.h     tablepref.h     scriptpref.h
                  \________________________           ___________________/                                            /                /                /                   /               /               /             /             /                /
                                           \         /_______________________________________________________________/________________/________________/___________________/_______________/_______________/_____________/_____________/________________/
                                            extcalc.h
  

File Description

extcalc:
Main Object of GUI, includes menus, tab initialisation, loading and saving config files and management of preferences.

calcwidget:
Complete calculator window (calculator tab), which includes and connects all calculator components.

calcinput:
This is the text field of the calculator. It does the calculation itself and controls user input and output.

calcpref:
Preferences dialog for calculator preferences.


graph:
Graphics main window (graphics tab). It includes and connects graph solving window and graph output window and the function table.

graphout:
This is the GL-component of the calculator. It precalculates the function graphs and shows them in an OpenGL-window.

graphsolve:
This class includes the User Interface of the graph analysis window and the special calculation alogithms for all the analysis functions. Screenshot saving is also controlled from there .

graphpref:
Preferences dialog for graphics preferences.


table:
Table window (table tab). This is the main window for calculating result tables of functions

tablepref:
Preferences dialog for tables.


matrixwidget:
Window form matrix and vector operations. In this window, the user can show and change all variables.


statistics:
The window for statistics, approximation and interpolation. It includes operations to calculate functions from lists data.


scriptedit:
Editor window for creating, editing and managing scripts

scriptio:
Console for the text input and output of calculator scripts

scriptpref:
Preferences dialog for scripts


buttons:
This object includes both button groups of the calculator.

calctable:
Overloaded QT-table which can show text in different colors.

functiontable:
Overloaded calctable class, which manages the functions strings for graphs and tables. It can also manage the function preferences like color, type, ...

catalog:
Overloaded QPopupMenu which includes sorted lists of all calculator operations and functions

global:
This object includes accerelated calculator class and all needed subroutines. It also includes the script class for running calculator scripts and functions for processing configfiles and unicode. In it's header file, all macros and the Preferences struct are defined.

3. Mathematical Functions

Two classes were used to process a calculation. The Calculate class and the Script class.
The normal calculator and the script interpreter use the script class. The Calculate class is used for graph drawing, function tables and function analysis. The console calculator calc only uses the Script class. All mathematical functions and classes are located in the global.h and global.cpp source files.

3.1 Important Basic Functions

There are several extra functions, that don't belong to any of the calculator classes, which were needed for the parsers.
This chapter describes them.

String Operations: strcut

The string operations were used to simplify string modifications in the parser and preprocessor algorithms.

Prototype:
char*strcut(char*src,int index,int len=1);

Description:
This function cuts out some characters from the given string and returns a pointer to the new string. Parameters are the source string, the start index and the number of characters to cut out.
The returned char pointer represents a newly allocated string, allocated with new.

String Operations: strins

Prototype:
char*strins(char*dest,const char*src,int index);

Description:
This function inserts the string src into the string dest at position index. It returns a pointer on the result string. The memory for the result string is allocated with the new operator inside the function.

String Operations: strcopy

Prototype:
int strcopy(char*dest,char*src,int len);

Description:
This function copies a part of the length len from src to dest. The dest string must be allocated before calling this function. It must be large enough for inserting. If you don't want to copy the string to the start of dest, use for example
 dest[start_index]
instead of dest.

String Operations: strreplace

Prototype:
char* strreplace(char*st,int index,int len,char*rep);

Description:
This function replaces the part of the string str with the lenght len from position index through the string rep. When the replacement is longer than len, the string will be resized. Return value is the new string, resized by realloc.

String Operations: strinsert

Prototype:
char* strinsert(char*st,int index,char*ins);

Description:
This function inserts the string ins into the string st at positon index. The string is resized by realloc. The return value is the new string.

Search Functions: bracketFind

The search functions are an important part of the parser algorithms, to find the relevant parts of a string.

Prototype:
int bracketFind(char* string,char* searchString, int start=0);

Description:
This functions searches the string string for the expression searchString. But it searches only outside of brackets. It counts the following as brackets:
( [ { "
Only if all found open brackets were closed, it continues searching. It is possible to search for one of the brackets. You can also set the search start index.

Search Functions: bracketFindRev

Prototype:
int bracketFindRev(char* string,char* searchString, int start=-1);

Description:
This function does the same as the function above, but it searches from the end to the start of the string. The search start index can also be set. -1 means always start at the end.

Preprocessor Functions: preprocessor

Prototype:
char* preprocessor(char*,Preferences*,bool);

Prototype:
char* preprocessor(QString*,Preferences*,bool);

Description:
This is the main function which should be used to preprocess the input string of a calculaton.
It can be called with a char pointer or with a QString pointer. When it is called with a QString, the unicode signs were replaced through the ascii ascii commands by the removeUnicode function.
The parameters are the input string, a pointer to the current preferences struct and a flag weather the the string should be treated as script or as normal calculation. If this parameter is false, the comments will not be removed and the macro preprocessor and the preferences preprocessor will not be run.
This function allways runs

Preprocessor Functions: preferencesPreprocessor

Prototype:
char* preferencesPreprocessor(char*,Preferences*);

Description:
This function checks the input string for #config commands. The function sets the preferences in the Preferences struct which it receives and removes the commands from the string. The return value is the new string without #config commands. This function should only be used for scripts.

Preprocessor Functions: macroPreprocessor

Prototype:
char* macroPreprocessor(char*);

Description:
The macro preprocessor interprets the #define commands and replaces the macros in the given string. The return value is a string with replaced macros.

Preprocessor Functions: cleanString

Prototype:
char* cleanString(char*,Preferences*);

Description:
This function removes whitespace from the string and replaces some constants and commands. The return value is the result string.

Preprocessor Functions: removeUnicode

Prototype:
char* removeUnicode(QString*);

Description:
This function creates a char* form a QString. It replaces all unicode commands through the ascii text commands.

Preprocessor Functions: removeComments

Prototype:
char* removeComments(char*);

Description:
This function removes the comments from the input string. The return value is the resulting string without comments.

3.2 Class Description

There are two classes which can be used to process mathematical expressions. The Calculate class and the Script class. Both classes have the same base class called Math.
These classes build a tree that represents a matematical expression in the memory. Both classes include a parser method that builds the tree. This parser is normally ran by the constructor of the class.
When the constructer has built an object tree, the expression can be calculated with a second method. These method can be ran several times with different values of the variables.

Math class

This class contains some main parts, which are needed for both matematic classes. These are the declaration:
class Math
{
	protected:                                          //These are the variables, needed for Calculate and Script
	Variable*vars;                                      //The variables array for Calc
	Preferences*pref;                                   //The preferences for this calculation
	Math*parent;                                        //A pointer to the parent object
	                                                    //At the root object, this is set to NULL
	Math *vertObj,*horzObj;                             //Pointers to the following objects
	double number;                                      //A variable as temporary memory for calculations and to store
	                                                    //the value of constants
	int var;                                            //if the object represents a variable, this contains the index (A is 0)
	int operation;                                      //this variable stores the operation code
	                                                    //the operation codes are defined in global.h
	public:
	Math(Math*par,Preferences*pr,Variable*va);          //constructor
	virtual ~Math();                                    //destructor
	
	int getOperation();                                 //returns the operation code of the object
	virtual double calc() {return 0.0;}                 //the following virtual methods run the calculator
	virtual double calcVertObj() {return 0.0;}          //they run recursive
	virtual double calcHorzObj() {return 0.0;}          //calc is overloaded in Calculate
	
	virtual Number exec() {Number r;r.type=NNONE;return r;}       //exec ist used in the Script class
	virtual Number execVertObj() {Number r;r.type=NNONE;return r;}
	virtual Number execHorzObj() {Number r;r.type=NNONE;return r;}

	virtual int split(char*){return 0;}                 //this method is used to run the interpreter
	                                                    //normally, this is done by the contructor, so you don't have to use it
	virtual char* parse(char*){return 0;}               //for the Script parser, this second method is needed
};                                                      //it contains the parser itself, while split decides how to run it
   

Calculate class

This is a very fast calculator class. I can not process script commands, but it contains all calculator commands, including integration and differentiation. It uses double variables for calculation, so the precision is limited to 15 decimal digits.
This class is used for drawing graphs and analyse functions.
This is the declaration:
  class Calculate :public Math
{
	virtual int split(char* line);			//this private method contains the script parser
											//the constructor runs it automatically
	public:
	Calculate(Math *par,char* line,Preferences*pr,Variable*va) :Math((Math*)par,pr,va);    //constructor
	~Calculate();                                                                          //destructor

	virtual double calc();                  //the following methods can be used to run the calculation after building the object tree
	virtual double calcVertObj();
	virtual double calcHorzObj();
};

Script class

The script class provides lots of matematical operations, complex numbers, string operations, matrix- and vector-processing and script commands. It uses a Number struct for calculations.
This class is used for the calculator, to run scripts and to draw and analyze complex functions.
This is the declaration:

class Script :public Math
{
	Number value;                           //Variable to store values and temporary memory for calculation
	Math*nextObj,*vertObj2,*vertObj3;       //additional pointers to build the tree
	ThreadSync*eventReciver;                //structure for synchronisation with the main application
	                                        //and for extra preferences
	                                        //it also contains the variables array
	private:
	inline bool resizeVar(int var,int newlen);  //method to manage the variables memory

	public:

	Script(Script*par,char*line,Preferences*pr,Variable*va,ThreadSync*evrec) :Math((Math*)par,pr,va);    //constructor
	~Script();                              //destructor
	char*parse(char*line);                  //the two methods to build the object tree
	virtual int split(char* line);


	virtual double calc();                  //methods to run calculator
	virtual double calcVertObj();
	virtual double calcHorzObj();

	virtual Number exec();
	virtual Number execVertObj();
	virtual Number execHorzObj();

};

3.3 Usage of the Matematical Classes

Variables and Preferences

The Script class and the Calculate class need a Preferences structure. This structure contains information about the calculator mode, how to process angles and if complex numbers are enabled.
The Preferences struct of Extcalc also includes the preferences for the Extcalc user interface.
Here is the Preferences Struct of Calc. It does only contain preferences for the Math classes:
struct Preferences
{
	int angle;                  //angle type DEG,RAD,GRA
	int outputType;             //how to format output (not important for Math classes)
	int outputLength;           //number of output digits
	int calcType;               //calculator mode BASE for logic operations, SCIENTIFIC for normal operation
	int base;                   //base for BASE-mode BIN,DEC,OCT,HEX
	int precision;              //maximum possible precision on this system
	bool complex;               //enable or disable complex numbers
};
  
This structure must be filled, and Script and Calculate will get a pointer to this structure.

The Calculate class uses an array of double variables to store variables.
Here is the definition of the data structure:
  typedef double Variable;
  
Calc and Extcalc need a pointer to an array of Variable-Elements.
The array must have 27 elements for variables from A to Z and the answer memory
No furter initialisation is needed, but you may want to set all elements to 0 or to a stored value.
A short example code:
  Variable *vars=(Variable*)malloc(sizeof(Variable)*27);
  


Extcalc needs an additional struct

Calculate

First, you need the string that contains the matematic operations to process. The memory for this string must be allocated by malloc.
char input[]="3+4*5sinx";
char*operation=(char*)malloc(strlen(input+1));
memcpy(operation,input,strlen(input)+1);
This string must be processed by the preprocessor, which returns another string.
 operation=preprocessor(operations,&pref); //returns 3+4*5*sinX
The returend string can be used to generate an object tree.
This object tree represents the matematical operations in the memory.
Calculate calc(NULL,operation,&pref,vars);
Now, the calc object has been created, and it can be used to run the operations.
double result=calc.calc(); calc() can be used several times with different variable values
for(int c=0; c<100; c++)
{
    vars[23]=(double)c;               //x is the 23rd element of the vars array
    results[c]=calc.calc();
}

4. Internal Interfaces

This chapter of the of the documentation describes the internal communication structures of Extcalc.

4.1 Basic Structures

Most of the internal internal communication is based on structs in which the information is stored.
Here is a list of these structs with a short description

Preferences

This is the main preferences struct of Extcalc. It holds all configuration information, including functions for graph drawing. The script is defined in global.h.
Every object in Extcalc which uses the Preferences has setPref method which updates its preferences and a prefChange signal which shows that it has changed the preferences. The prefChange signal is sent to the getPref slot of the parent object, which submits it to its parent, until it reaches the main object. The main object calls the setPref methods of its childs and so on. So do all objects receive the new preferences.
struct Preferences
{
	int angle;                                           //angle type: DEG,RAD or GRA
	int outputType;                                      //calculator output format
	int outputLength;                                    //number of shown digits
	int precision;                                       //information about the maximum precision of the computer (in digits)
	bool shift;                                          //shift key pressed?
	bool alpha;                                          //alpha key pressed?
	bool hyp;                                            //hyp key pressed?
	bool showWindows[8];                                 //information, which tabs are visible
	double xmin,xmax,ymin,ymax,zmin,zmax;                //coordinate system (cartesian)
	double rasterSizeX,rasterSizeY,rasterSizeZ;          //coordinate system raster
	double radiusMax,angleMax;                           //polar coordinate system
	double rasterSizeRadius,rasterSizeAngle;             //polar coordinate system raster
	double parameterStart,parameterEnd;                  //start and end value for drawing parameter function
	double dynamicStart,dynamicEnd;                      //start and and value for dynamic parameter
	double nyquistStart,nyquistEnd;                      //start and and value for nyquist plot
	double tableXStart,tableXEnd,tableZStart,tableZEnd;  //start and and value for tables
	double tableAValue;                                  //fixed A value for tables
	int parameterSteps;                                  //number of steps for drawing parameter functions
	int dynamicSteps;                                    //number of steps for dynamic parameter
	int dynamicDelay;                                    //delay time for dynamic graphs
	int nyquistSteps;                                    //number of steps for drawing nyquist plots
	int prec2dSteps;                                     //number of steps for drawing normal functions
	int prec3dSteps;                                     //number of steps for 3D-graphs
	int solvePrec;                                       //precision for graph analysis functions
	int tableXSteps,tableZSteps;                         //number of steps for calculating tables
	bool raster;                                         //show coordinate system raster
	bool axis;                                           //show axes
	bool label;                                          //show labels
	bool autosize;                                       //correct size of coordinate system
	bool moveUpDown;                                     //for dynamic functions
	bool show3dGrid;                                     //not active
	bool logNyquistSteps;                                //use logarithmic steps for nyquist plots
	bool complex;                                        //enable support for complex numbers
	bool clearScriptMemory;                              //delete script variables before running script
	bool showStatLines;                                  //view preferences for statistics functions
	bool showStatPoints;
	bool statAutoClear;
	int graphType;                                       //coordinate system (2D, 3D, polar)
	int calcType;                                        //calculator state (scientific or logic mode)
	int tableType;                                       //function type for tables (2D, 3D, polar, ...)
	int base;                                            //numeral base for logic mode
	int scriptGraphicsMode;                              //is script text-based, 2D-graphics or 3D-graphics
	QString scriptPath;                                  //path of the root-directory for scripts
	QString scriptDirName;                               //script code directory
	QString dataDirName;                                 //script data directory (for file operations)
	QString*functions;                                   //function list (for graph drawing, tables, ...)
	bool*activeFunctions;                                //which of the functions were currently shown
	int*functionTypes;                                   //function types of all functions
	bool*dynamicFunctions;                               //dynamic flag for all functions
	QColor*functionColors;                               //colors of the functions
	QString drawText;
};

ThreadSync

This structure is used for the communication between the a running script in the script interpreter and the object which has started the script. Data transfer is done by QEvents. The struct also includes variables for load balancing between script and user interface and pointers to the variables memory.
struct ThreadSync
{
	QMutex*mutex;                                        //mutex to lock thread (for load balancing)
	QObject*eventReciver;                                //receiver of the Events
	void*data;                                           //pointer to the event data
	int type;                                            //event type
	int sleepTime;                                       //variable to delay script execution (for load balancing)
	int status;                                          //status variable (must be set that the script reads the status flags)
	int eventCount;                                      //number of events in the event loop (for load balancing)
	bool usleep;                                         //sleep flag (for load balancing)
	bool exit;                                           //exit flag (immediately stop execution of the script)
	bool bbreak;                                         //stop the next loop
	bool bcontinue;                                      //continue with the next step of a loo
	bool calcMode;                                       //running a script or a simple calculation?
	int numlen[VARNUM];                                  //number of elements allocated for each variable
	int dimension[VARNUM][VARDIMENSIONS];                //size of the dimensions of every variable
	Number**vars;                                        //pointers to the variables memory
	List <Math*>subprograms;                             //pointers to the root objects of the subroutines
	List <char*>subprogramPath;                          //pathes to identify the subroutines (needed for interpreter)
};

4.2 Variables

The calculator uses different types of variables for calculation. This chapter describes these variables.

Variable

This variable definition is used for the Calculate class. This class can only process real values. It is optimal for fast graph drawing.
typedef long double Variable;

Complex

The script interpreter supports complex numbers for calculation. For these variables, an additional definition for a complex number is needed. This sort of complex numbers can be used with the C++ math functions.
typedef complex  Complex;

Number

The number struct is used for the script interpreter. It can hold several different data types in one strut.
struct Number
{

	complex <long double> fval;                 //complex floating point value
	long long ival;                             //64-bit integer value
	bool bval;                                  //boolean value
	char*cval;                                  //string value
	int type;                                   //variable type (NFLOAT, NINT, NBOOL or NCHAR)
};

4.3 Config file and Preferences

All the preferences which were saved when the program is closed, are stored in the Preferences struct.
These preferences were saved in a single file in the .extcalc directory in the users home directory.
The configuration file is named extcalc.conf.
The calculator also stores the floating point values of all variables and the lists for statistics functions.
By default, the script code and data is also stored in a sub directory in .extcalc.

5. Mathematical Algorithms

6. Installation Files

The installation package uses the standard unix installer with configure script and Makefile. The configure script is created from the configure.ac file with autoconf. The makefiles were created by running the configure script before the installation. The configure script uses the information of the Makefile.in files to create the Makefiles. This Makefile.in files were created with automake from the Makefile.am files.
The Installation package includes a doc directory with all documentation, a src directory with the source code and a share directory with all files that will be installed (icons, example scripts, ...).