diff options
Diffstat (limited to 'kmplot/kmplot/parser.cpp')
-rw-r--r-- | kmplot/kmplot/parser.cpp | 1165 |
1 files changed, 1165 insertions, 0 deletions
diff --git a/kmplot/kmplot/parser.cpp b/kmplot/kmplot/parser.cpp new file mode 100644 index 00000000..1f3fa011 --- /dev/null +++ b/kmplot/kmplot/parser.cpp @@ -0,0 +1,1165 @@ +/* +* KmPlot - a math. function plotter for the KDE-Desktop +* +* Copyright (C) 1998, 1999 Klaus-Dieter M�ler +* 2000, 2002 kd.moeller@t-online.de +* +* This file is part of the KDE Project. +* KmPlot is part of the KDE-EDU Project. +* +* 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, Cambridge, MA 02110-1301, USA. +* +*/ + +// standard c(++) includes +#include <stdlib.h> +#include <stdio.h> +#include <math.h> + +//KDE includes +#include <kdebug.h> +#include <klocale.h> +#include <kmessagebox.h> + +// local includes +#include "parser.h" +#include "settings.h" +#include "xparser.h" + +double Parser::m_anglemode = 0; + +/// List of predefined functions. +Parser::Mfkt Parser::mfkttab[ FANZ ]= +{ + {"tanh", ltanh}, // Tangens hyperbolicus + {"tan", ltan}, // Tangens + {"sqrt", sqrt}, // Square root + {"sqr", sqr}, // Square + {"sinh", lsinh}, // Sinus hyperbolicus + {"sin", lsin}, // Sinus + {"sign", sign}, // Signum + {"sech", sech}, // Secans hyperbolicus + {"sec", sec}, // Secans + {"log", llog}, // Logarithm base 10 + {"ln", ln}, // Logarithm base e + {"exp", exp}, // Exponential function base e + {"coth", coth}, // Co-Tangens hyperbolicus + {"cot", cot}, // Co-Tangens = 1/tan + {"cosh", lcosh}, // Cosinus hyperbolicus + {"cosech", cosech}, // Co-Secans hyperbolicus + {"cosec", cosec}, // Co-Secans + {"cos", lcos}, // Cosinus + {"artanh", artanh}, // Area-tangens hyperbolicus = inverse of tanh + {"arsinh", arsinh}, // Area-sinus hyperbolicus = inverse of sinh + {"arsech", arsech}, // Area-secans hyperbolicus = invers of sech + {"arctanh", artanh}, // The same as artanh + {"arcsinh", arsinh}, // The same as arsinh + {"arccosh", arcosh}, // The same as arcosh + {"arctan", arctan}, // Arcus tangens = inverse of tan + {"arcsin", arcsin}, // Arcus sinus = inverse of sin + {"arcsec", arcsec}, // Arcus secans = inverse of sec + {"arcoth", arcoth}, // Area-co-tangens hyperbolicus = inverse of coth + {"arcosh", arcosh}, // Area-cosinus hyperbolicus = inverse of cosh + {"arcosech", arcosech}, // Area-co-secans hyperbolicus = inverse of cosech + {"arccot", arccot}, // Arcus co-tangens = inverse of cotan + {"arccosec", arccosec}, // Arcus co-secans = inverse of cosec + {"arccos", arccos}, // Arcus cosinus = inverse of cos + {"abs", fabs} // Absolute value +}; + + + +Ufkt::Ufkt() +{ + id = 0; + mem = 0; + mptr = 0; + k = 0; + oldy = 0; + f_mode = true; + f1_mode = false; + f2_mode = false; + integral_mode = false; + integral_use_precision = false; + linewidth = 0; + f1_linewidth = 0; + f2_linewidth = 0; + integral_linewidth = 0; + double dmin = 0.0; + dmax = 0.0; + oldyprim = 0.0; + oldx = 0.0; + starty = 0.0; + startx = 0.0; + integral_precision = 0.0; + use_slider = -1; + usecustomxmin = false; + usecustomxmax = false; + +} + +Ufkt::~Ufkt() +{ +} + + +Parser::Parser() +{ + ps_init(); +} + + +void Parser::ps_init() +{ + evalflg=0; + Ufkt temp; + temp.fname = temp.fvar = temp.fpar = temp.fstr = ""; + temp.mem=new unsigned char [MEMSIZE]; + ufkt.append(temp ); + current_item = ufkt.begin(); +} + + +Parser::~Parser() +{ + kdDebug() << "Exiting......" << endl; + for( QValueVector<Ufkt>::iterator it = ufkt.begin(); it != ufkt.end(); ++it) + { + kdDebug() << "Deleting something... :-)" << endl; + delete [](*it).mem; + } +} + +void Parser::setAngleMode(int angle) +{ + if(angle==0) + m_anglemode = 1; + else + m_anglemode = M_PI/180; +} + +void Parser::setDecimalSymbol(const QString c) +{ + m_decimalsymbol = c; +} + +double Parser::anglemode() +{ + return m_anglemode; +} + + +uint Parser::getNewId() +{ + uint i = 0; + bool found = false; + while (1 ) + { + found = false; + for( QValueVector<Ufkt>::iterator it = ufkt.begin(); it != ufkt.end(); ++it) + { + if (it->id == i && !it->fname.isEmpty()) + { + found = true; + break; + } + } + if (!found) + return i; + ++i; + } +} + +double Parser::eval(QString str) +{ + stack=new double [STACKSIZE]; + stkptr=stack; + evalflg=1; + + fix_expression(str,0); + + if ( str.contains('y')!=0) + { + err=9; + delete []stack; + return 0; + } + for (uint i=0;i<str.length();i++ ) + if (str.at(i).category() == QChar::Letter_Uppercase) + { + err=14; + delete []stack; + return 0; + } + + lptr=str.latin1(); + err=0; + heir1(); + if(*lptr!=0 && err==0) err=1; + evalflg=0; + double const erg=*stkptr; + delete [] stack; + if(err==0) + { + errpos=0; + return erg; + } + else + { + errpos=lptr-(str.latin1())+1; + return 0.; + } +} + +int Parser::idValue(int const ix) +{ + if ( ix >=0 && ix<(int)ufkt.count() ) // range check + { + if ( !( ufkt.count()==1 && ufkt[0].fname.isEmpty() ) ) + return ufkt[ix].id; + } + return -1; + +} + +int Parser::ixValue(uint const id) +{ + int ix=0; + for( QValueVector<Ufkt>::iterator it = ufkt.begin(); it != ufkt.end(); ++it) + { + if ( it->id ==id) + return ix; + ix++; + } + return -1; +} + +double Parser::fkt(uint const id, double const x) +{ + for( QValueVector<Ufkt>::iterator it = ufkt.begin(); it != ufkt.end(); ++it) + { + if ( it->id == id) + return fkt(it,x); + } + err=13; + return 0; +} + +double Parser::fkt(Ufkt *it, double const x) +{ + double *pd, (**pf)(double); + double *stack, *stkptr; + uint *puf; + it->mptr=it->mem; + stack=stkptr= new double [STACKSIZE]; + + while(1) + { + switch(*it->mptr++) + { + case KONST: + pd=(double*)it->mptr; + *stkptr=*pd++; + it->mptr=(unsigned char*)pd; + break; + case XWERT: + *stkptr=x; + break; + case YWERT: + *stkptr=it->oldy; + break; + case KWERT: + *stkptr=it->k; + break; + case PUSH: + ++stkptr; + break; + case PLUS: + stkptr[-1]+=*stkptr; + --stkptr; + break; + case MINUS: + stkptr[-1]-=*stkptr; + --stkptr; + break; + case MULT: + stkptr[-1]*=*stkptr; + --stkptr; + break; + case DIV: + if(*stkptr==0.)*(--stkptr)=HUGE_VAL; + else + { + stkptr[-1]/=*stkptr; + --stkptr; + } + break; + case POW: + stkptr[-1]=pow(*(stkptr-1), *stkptr); + --stkptr; + break; + case NEG: + *stkptr=-*stkptr; + break; + case FKT: + pf=(double(**)(double))it->mptr; + *stkptr=(*pf++)(*stkptr); + it->mptr=(unsigned char*)pf; + break; + case UFKT: + { + puf=(uint*)it->mptr; + uint id = *puf++; + for( QValueVector<Ufkt>::iterator ite = ufkt.begin(); ite != ufkt.end(); ++ite) + { + if ( ite->id == id) + { + *stkptr=fkt(ite, *stkptr); + break; + } + } + it->mptr=(unsigned char*)puf; + break; + } + case ENDE: + double const erg=*stkptr; + delete [] stack; + return erg; + } + } +} + +int Parser::addfkt(QString str) +{ + QString const extstr = str; + stkptr=stack=0; + err=0; + errpos=1; + const int p1=str.find('('); + int p2=str.find(','); + const int p3=str.find(")="); + fix_expression(str,p1+4); + + if(p1==-1 || p3==-1 || p1>p3) + { err=4; + return -1; + } + if ( p3+2 == (int) str.length()) //empty function + { err=11; + return -1; + } + if(p2==-1 || p2>p3) p2=p3; + + if( fnameToId(str.left(p1))!=-1 ) + { + err=8; + return -1; + } + else + err=0; + + if (str.mid(p1+1, p2-p1-1) == "e") + { err=4; + return -1; + } + + if ( ufkt.begin()->fname.isEmpty() ) + { + ufkt.begin()->id = 0; + //kdDebug() << "ufkt.begin()->id:" << ufkt.begin()->id << endl; + } + else + { + Ufkt temp; + if ( !temp.fstr.isEmpty() && temp.fstr.at(0) == 'y') + temp.id = ufkt.last().id; //the function belongs to the last inserted function + else + temp.id = getNewId(); + temp.mem=new unsigned char [MEMSIZE]; + ufkt.append(temp ); + } + QString const fname = str.left(p1); + Ufkt *temp = &ufkt.last(); + temp->fstr=extstr; + temp->mptr = 0; + temp->fname=fname; + temp->fvar=str.mid(p1+1, p2-p1-1); + if(p2<p3) temp->fpar=str.mid(p2+1, p3-p2-1); + else temp->fpar=""; //.resize(1); + + kdDebug() << "temp.id:" << temp->id << endl; + + if ( temp->fname != temp->fname.lower() ) //isn't allowed to contain capital letters + { + delfkt(temp); + err=12; + return -1; + } + current_item = temp; + mem=mptr=temp->mem; + lptr=(str.latin1())+p3+2; + heir1(); + if(*lptr!=0 && err==0) err=1; // Syntaxfehler + addtoken(ENDE); + if(err!=0) + { + errpos=lptr-(str.latin1())+1; + delfkt(temp); + return -1; + } + errpos=0; + return temp->id; //return the unique ID-number for the function +} + +void Parser::reparse(int ix) +{ + reparse( &ufkt[ix] ); +} + +void Parser::reparse(Ufkt *item) +{ + kdDebug() << "Reparsing: " << item->fstr << endl; + QString str = item->fstr.latin1(); + err=0; + errpos=1; + + const int p1=str.find('('); + int p2=str.find(','); + const int p3=str.find(")="); + + fix_expression(str,p1+4); + + if(p1==-1 || p3==-1 || p1>p3) + { err=4; + return; + } + if ( p3+2 == (int) str.length()) //empty function + { err=11; + return; + } + if(p2==-1 || p2>p3) p2=p3; + + if (str.mid(p1+1, p2-p1-1) == "e") + { err=4; + return; + } + + item->fname=str.left(p1); + item->fvar=str.mid(p1+1, p2-p1-1); + if(p2<p3) item->fpar=str.mid(p2+1, p3-p2-1); + else item->fpar=""; + + if ( item->fname != item->fname.lower() ) //isn't allowed to contain capital letters + { + err=12; + return; + } + + //ixa=ix; + current_item = item; + mem=mptr=item->mem; + lptr=(str.latin1())+p3+2; + heir1(); + if(*lptr!=0 && err==0) err=1; // Syntaxfehler + addtoken(ENDE); + errpos=0; +} + +void Parser::fix_expression(QString &str, int const pos) +{ + str.remove(" " ); + + //insert '*' when it is needed + QChar ch; + bool function = false; + for(uint i=pos; i < str.length();i++) + { + ch = str.at(i); + if ( str.at(i+1)=='(' && ch.category()==QChar::Letter_Lowercase ) + { + QString str_function(ch); + int n=i-1; + while (n>0 && str.at(n).category() == QChar::Letter_Lowercase ) + { + str_function.prepend(str.at(n)); + --n; + } + if (str_function == "tanh" || str_function == "tan" || str_function =="sqrt" || str_function =="sqr" || str_function =="sin" || str_function =="sinh" || str_function =="sign" || str_function =="sech" || str_function =="sec" || str_function =="log" || str_function =="ln" || str_function =="exp" || str_function =="coth" || str_function =="cot" || str_function =="cosh" || str_function =="cosech" || str_function =="cosec" || str_function =="cos" || str_function =="artanh" || str_function =="arsinh" || str_function =="arsech" || str_function =="arctan" || str_function =="arcsin" || str_function =="arcsec" || str_function =="arcoth" || str_function =="arcosh" || str_function =="arcosech" || str_function =="arccot" || str_function =="arccosec" || str_function =="arccos" || str_function =="abs" || str_function=="arctanh" || str_function=="arcsinh" || str_function=="arccosh") + function = true; + else + for( QValueVector<Ufkt>::iterator it = ufkt.begin(); it != ufkt.end(); ++it) + { + for ( int j=i; j>0 && (str.at(j).isLetter() || str.at(j).isNumber() ) ; --j) + { + if ( it->fname == str.mid(j,i-j+1) ) + function = true; + } + } + } + else if (function) + function = false; + + if( (ch.isNumber() || ch.category()==QChar::Letter_Uppercase )&& ( str.at(i-1).isLetter() || str.at(i-1) == ')' ) || (ch.isLetter() && str.at(i-1)==')') ) + str.insert(i,'*'); + else if( (ch.isNumber() || ch == ')' || ch.category()==QChar::Letter_Uppercase) && ( str.at(i+1).isLetter() || str.at(i+1) == '(' ) || (ch.isLetter() && str.at(i+1)=='(' && !function ) ) + { + str.insert(i+1,'*'); + i++; + } + } + QString str_end = str.mid(pos); + str_end = str_end.replace(m_decimalsymbol, "."); //replace the locale decimal symbol with a '.' + str.truncate(pos); + str.append(str_end); + //kdDebug() << "str:" << str << endl; +} + +bool Parser::delfkt( Ufkt *item) +{ + kdDebug() << "Deleting id:" << item->id << endl; + if (!item->dep.isEmpty()) + { + KMessageBox::error(0,i18n("This function is depending on an other function")); + return false; + } + for(QValueVector<Ufkt>::iterator it1=ufkt.begin(); it1!=ufkt.end(); ++it1) + { + if (it1==item) + continue; + for(QValueList<int>::iterator it2=it1->dep.begin(); it2!=it1->dep.end(); ++it2) + if ( (uint)*it2 == item->id ) + it2 = it1->dep.erase(it2); + } + + if ( ufkt.count()==1 ) + { + //kdDebug() << "first item, don't delete" << endl; + item->fname=""; + } + else + { + //kdDebug() << "Deleting something" << endl; + QChar const extstr_c = item->fstr.at(0); + uint const id = item->id; + delete []item->mem; + ufkt.erase(item); + if ( extstr_c == 'x') + { + int const ix = ixValue(id+1); + if (ix!= -1 && ufkt[ix].fstr.at(0) == 'y') + delfkt( &ufkt[ix]); + } + else if ( extstr_c == 'y') + { + int const ix = ixValue(id-1); + if (ix!= -1 && ufkt[ix].fstr.at(0) == 'x') + delfkt( &ufkt[ix]); + } + } + return true; +} + +bool Parser::delfkt(uint id) +{ + int ix = ixValue(id); + if ( ix!=-1 && delfkt(&ufkt[ix])) + return true; + else + return false; +} + +uint Parser::countFunctions() +{ + uint const count = ufkt.count(); + if (count == 1 && ufkt.begin()->fname.isEmpty()) + return 0; + else + return count; +} + +void Parser::heir1() +{ + char c; + heir2(); + if(err!=0) return ; + + while(1) + { + switch(c=*lptr) + { + default: + return ; + + case ' ': + ++lptr; + continue; + case '+': + case '-': + ++lptr; + addtoken(PUSH); + heir2(); + if(err!=0) + return; + } + switch(c) + { + case '+': + addtoken(PLUS); + break; + case '-': + addtoken(MINUS); + } + } +} + + +void Parser::heir2() +{ + if(match("-")) + { + heir2(); + if(err!=0) + return; + addtoken(NEG); + } + else + heir3(); +} + + +void Parser::heir3() +{ + char c; + heir4(); + if(err!=0) + return; + while(1) + { + switch(c=*lptr) + { + default: + return; + case ' ': + ++lptr; + continue; + case '*': + case '/': + ++lptr; + addtoken(PUSH); + heir4(); + if(err!=0) + return ; + } + switch(c) + { + case '*': + addtoken(MULT); + break; + case '/': + addtoken(DIV); + } + } +} + + +void Parser::heir4() +{ + primary(); + if(err!=0) + return; + while(match("^")) + { + addtoken(PUSH); + primary(); + if(err!=0) + return; + addtoken(POW); + } +} + + +void Parser::primary() +{ + if(match("(")) + { + heir1(); + if(match(")")==0) + err=2; // fehlende Klammer + return; + } + int i; + for(i=0; i<FANZ; ++i) + { + if(match(mfkttab[i].mfstr)) + { + primary(); + addtoken(FKT); + addfptr(mfkttab[i].mfadr); + return; + } + } + for( QValueVector<Ufkt>::iterator it = ufkt.begin(); it != ufkt.end(); ++it) + { + if(QString(lptr)=="pi" || QString(lptr)=="e") continue; + + if( match(it->fname.latin1()) ) + { + if (it == current_item) + { + err=9; + return; + } + primary(); + addtoken(UFKT); + addfptr( it->id ); + it->dep.append(current_item->id); + return; + } + } + + // A constant + if(lptr[0] >='A' && lptr[0]<='Z' ) + { + char tmp[2]; + tmp[1] = '\0'; + for( i = 0; i< (int)constant.size();i++) + { + tmp[0] = constant[i].constant; + if ( match( tmp) ) + { + addtoken(KONST); + addwert(constant[i].value); + return; + } + } + err = 10; + return; + } + + if(match("pi")) + { + addtoken(KONST); + addwert(M_PI); + return; + } + + if(match("e")) + { + addtoken(KONST); + addwert(M_E); + return; + } + //if(match(ufkt[ixa].fvar.latin1())) + if(match(current_item->fvar.latin1())) + { + addtoken(XWERT); + return; + } + + if(match("y")) + { + addtoken(YWERT); + return; + } + + //if(match(ufkt[ixa].fpar.latin1())) + if(match(current_item->fpar.latin1())) + { + addtoken(KWERT); + return; + } + + char *p; + double const w=strtod(lptr, &p); + if(lptr!=p) + { + lptr=p; + addtoken(KONST); + addwert(w); + } + else + err=1; // Syntax-Fehler +} + + +int Parser::match(const char *lit) +{ + + const char *p; + if(*lit==0) + return 0; + while(*lptr==' ') + ++lptr; + p=lptr; + + while(*lit) + { + if(*lit++!=*p++) + return 0; + } + lptr=p; + return 1; +} + + +void Parser::addtoken(unsigned char token) +{ + if(stkptr>=stack+STACKSIZE-1) + { + err=7; + return; + } + + if(evalflg==0) + { + if(mptr>=&mem[MEMSIZE-10]) + err=6; + else + *mptr++=token; + + switch(token) + { + case PUSH: + ++stkptr; + break; + case PLUS: + case MINUS: + case MULT: + case DIV: + case POW: + --stkptr; + } + } + else switch(token) + { + case PUSH: + ++stkptr; + break; + case PLUS: + stkptr[-1]+=*stkptr; + --stkptr; + break; + + case MINUS: + stkptr[-1]-=*stkptr; + --stkptr; + break; + case MULT: + stkptr[-1]*=*stkptr; + --stkptr; + break; + case DIV: + if(*stkptr==0.) + *(--stkptr)=HUGE_VAL; + else + { + stkptr[-1]/=*stkptr; + --stkptr; + } + break; + + case POW: + stkptr[-1]=pow(*(stkptr-1), *stkptr); + --stkptr; + break; + case NEG: + *stkptr=-*stkptr; + } +} + + +void Parser::addwert(double x) +{ + double *pd=(double*)mptr; + + if(evalflg==0) + { + if(mptr>=&mem[MEMSIZE-10]) + err=6; + else + { + *pd++=x; + mptr=(unsigned char*)pd; + } + } + else + *stkptr=x; +} + + +void Parser::addfptr(double(*fadr)(double)) +{ + double (**pf)(double)=(double(**)(double))mptr; + if( evalflg==0 ) + { + if( mptr>=&mem[MEMSIZE-10] ) + err=6; + else + { + *pf++=fadr; + mptr=(unsigned char*)pf; + } + } + else + *stkptr=(*fadr)(*stkptr); +} + + +void Parser::addfptr(uint id) +{ + uint *p=(uint*)mptr; + if(evalflg==0) + { + if(mptr>=&mem[MEMSIZE-10]) err=6; + else + { + *p++=id; + mptr=(unsigned char*)p; + } + } + else + { + for( QValueVector<Ufkt>::iterator it = ufkt.begin(); it != ufkt.end(); ++it) + if ( it->id == id) + { + *stkptr=fkt(it, *stkptr); + break; + } + } +} + + +int Parser::fnameToId(const QString &name) +{ + for( QValueVector<Ufkt>::iterator it = ufkt.begin(); it != ufkt.end(); ++it) + { + if(name==it->fname) + return it->id; + } + return -1; // Name nicht bekannt +} + + +int Parser::parserError(bool showMessageBox) +{ + if (!showMessageBox) + return err; + switch(err) + { + case 1: KMessageBox::error(0, i18n("Parser error at position %1:\n" + "Syntax error").arg(QString::number(errpos)), "KmPlot"); + break; + case 2: KMessageBox::error(0, i18n("Parser error at position %1:\n" + "Missing parenthesis").arg(QString::number(errpos)), "KmPlot"); + break; + case 3: KMessageBox::error(0, i18n("Parser error at position %1:\n" + "Function name unknown").arg(QString::number(errpos)), "KmPlot"); + break; + case 4: KMessageBox::error(0, i18n("Parser error at position %1:\n" + "Void function variable").arg(QString::number(errpos)), "KmPlot"); + break; + case 5: KMessageBox::error(0, i18n("Parser error at position %1:\n" + "Too many functions").arg(QString::number(errpos)), "KmPlot"); + break; + case 6: KMessageBox::error(0, i18n("Parser error at position %1:\n" + "Token-memory overflow").arg(QString::number(errpos)), "KmPlot"); + break; + case 7: KMessageBox::error(0, i18n("Parser error at position %1:\n" + "Stack overflow").arg(QString::number(errpos)), "KmPlot"); + break; + case 8: KMessageBox::error(0, i18n("Parser error at position %1:\n" + "Name of function not free.").arg(QString::number(errpos)), "KmPlot"); + break; + case 9: KMessageBox::error(0, i18n("Parser error at position %1:\n" + "recursive function not allowed.").arg(QString::number(errpos)), "KmPlot"); + break; + case 10: KMessageBox::error(0, i18n("Could not find a defined constant at position %1." ).arg(QString::number(errpos)), + "KmPlot"); + break; + case 11: KMessageBox::error(0, i18n("Empty function"), "KmPlot"); + break; + case 12: KMessageBox::error(0, i18n("The function name is not allowed to contain capital letters."), "KmPlot"); + break; + case 13: KMessageBox::error(0, i18n("Function could not be found."), "KmPlot"); + break; + case 14: KMessageBox::error(0, i18n("The expression must not contain user-defined constants."), "KmPlot"); + break; + } + return err; +} + + + +// static +QString Parser::number( double value ) +{ + QString str = QString::number( value, 'g', 6 ); + str.replace( 'e', "*10^" ); +// kDebug() << "returning str="<<str<<endl; + return str; +} + + + +double ln(double x) +{ + return log(x); +} + +double llog(double x) +{ + return log10(x); +} + +double sign(double x) +{ + if(x<0.) + return -1.; + else + if(x>0.) + return 1.; + return 0.; +} + +double sqr(double x) +{ + return x*x; +} + +double arsinh(double x) +{ + return log(x+sqrt(x*x+1)); +} + + +double arcosh(double x) +{ + return log(x+sqrt(x*x-1)); +} + + +double artanh(double x) +{ + return log((1+x)/(1-x))/2; +} + +// sec, cosec, cot and their inverses + +double sec(double x) +{ + return (1 / cos(x*Parser::anglemode())); +} + +double cosec(double x) +{ + return (1 / sin(x*Parser::anglemode())); +} + +double cot(double x) +{ + return (1 / tan(x*Parser::anglemode())); +} + +double arcsec(double x) +{ + if ( !Parser::anglemode() ) + return ( 1/acos(x)* 180/M_PI ); + else + return acos(1/x); +} + +double arccosec(double x) +{ + return asin(1/x)* 1/Parser::anglemode(); +} + +double arccot(double x) +{ + return atan(1/x)* 1/Parser::anglemode(); +} + +// sech, cosech, coth and their inverses + + +double sech(double x) +{ + return (1 / cosh(x*Parser::anglemode())); +} + +double cosech(double x) +{ + return (1 / sinh(x*Parser::anglemode())); +} + +double coth(double x) +{ + return (1 / tanh(x*Parser::anglemode())); +} + +double arsech(double x) +{ + return arcosh(1/x)* 1/Parser::anglemode(); +} + +double arcosech(double x) +{ + return arsinh(1/x)* 1/Parser::anglemode(); +} + +double arcoth(double x) +{ return artanh(1/x)* 1/Parser::anglemode(); +} + +//basic trigonometry functions + +double lcos(double x) +{ + return cos(x*Parser::anglemode()); +} +double lsin(double x) +{ + return sin(x*Parser::anglemode()); +} +double ltan(double x) +{ + return tan(x*Parser::anglemode()); +} + +double lcosh(double x) +{ + return cosh(x*Parser::anglemode()); +} +double lsinh(double x) +{ + return sinh(x*Parser::anglemode()); +} +double ltanh(double x) +{ + return tanh(x*Parser::anglemode()); +} + +double arccos(double x) +{ + return acos(x) * 1/Parser::anglemode(); +} +double arcsin(double x) +{ + return asin(x)* 1/Parser::anglemode(); +} + +double arctan(double x) +{ + return atan(x)* 1/Parser::anglemode(); +} |